1 /*
2 * Copyright (c) 1997, 2015, Oracle and/or its affiliates. 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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 package javax.swing;
26
27
28 import java.beans.*;
29 import java.util.HashSet;
30 import java.util.Hashtable;
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
37 import java.awt.*;
38 import java.awt.event.*;
39 import java.awt.peer.LightweightPeer;
40
41 import java.applet.Applet;
42
43 import java.io.Serializable;
44 import java.io.ObjectOutputStream;
45 import java.io.ObjectInputStream;
46 import java.io.IOException;
47 import java.io.ObjectInputValidation;
48 import java.io.InvalidObjectException;
49 import java.util.concurrent.atomic.AtomicBoolean;
50
51 import javax.swing.border.*;
52 import javax.swing.event.*;
53 import javax.swing.plaf.*;
54 import static javax.swing.ClientPropertyKey.*;
55 import javax.accessibility.*;
56
57 import sun.awt.AWTAccessor;
58 import sun.awt.SunToolkit;
59 import sun.swing.SwingUtilities2;
60 import sun.swing.UIClientPropertyKey;
61
62 /**
63 * The base class for all Swing components except top-level containers.
64 * To use a component that inherits from <code>JComponent</code>,
65 * you must place the component in a containment hierarchy
66 * whose root is a top-level Swing container.
67 * Top-level Swing containers --
68 * such as <code>JFrame</code>, <code>JDialog</code>,
69 * and <code>JApplet</code> --
70 * are specialized components
71 * that provide a place for other Swing components to paint themselves.
72 * For an explanation of containment hierarchies, see
73 * <a
74 href="http://docs.oracle.com/javase/tutorial/uiswing/components/toplevel.html">Swing Components and the Containment Hierarchy</a>,
75 * a section in <em>The Java Tutorial</em>.
76 *
77 * <p>
78 * The <code>JComponent</code> class provides:
79 * <ul>
80 * <li>The base class for both standard and custom components
81 * that use the Swing architecture.
82 * <li>A "pluggable look and feel" (L&F) that can be specified by the
83 * programmer or (optionally) selected by the user at runtime.
84 * The look and feel for each component is provided by a
85 * <em>UI delegate</em> -- an object that descends from
86 * {@link javax.swing.plaf.ComponentUI}.
87 * See <a
88 * href="http://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html">How
89 * to Set the Look and Feel</a>
90 * in <em>The Java Tutorial</em>
91 * for more information.
92 * <li>Comprehensive keystroke handling.
93 * See the document <a
94 * href="http://docs.oracle.com/javase/tutorial/uiswing/misc/keybinding.html">How to Use Key Bindings</a>,
95 * an article in <em>The Java Tutorial</em>,
96 * for more information.
97 * <li>Support for tool tips --
98 * short descriptions that pop up when the cursor lingers
99 * over a component.
100 * See <a
101 * href="http://docs.oracle.com/javase/tutorial/uiswing/components/tooltip.html">How
102 * to Use Tool Tips</a>
103 * in <em>The Java Tutorial</em>
104 * for more information.
105 * <li>Support for accessibility.
106 * <code>JComponent</code> contains all of the methods in the
107 * <code>Accessible</code> interface,
108 * but it doesn't actually implement the interface. That is the
109 * responsibility of the individual classes
110 * that extend <code>JComponent</code>.
111 * <li>Support for component-specific properties.
112 * With the {@link #putClientProperty}
113 * and {@link #getClientProperty} methods,
114 * you can associate name-object pairs
115 * with any object that descends from <code>JComponent</code>.
116 * <li>An infrastructure for painting
117 * that includes double buffering and support for borders.
118 * For more information see <a
119 * href="http://www.oracle.com/technetwork/java/painting-140037.html#swing">Painting</a> and
120 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/border.html">How
121 * to Use Borders</a>,
122 * both of which are sections in <em>The Java Tutorial</em>.
123 * </ul>
124 * For more information on these subjects, see the
125 * <a href="package-summary.html#package_description">Swing package description</a>
126 * and <em>The Java Tutorial</em> section
127 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/jcomponent.html">The JComponent Class</a>.
128 * <p>
129 * <code>JComponent</code> and its subclasses document default values
130 * for certain properties. For example, <code>JTable</code> documents the
131 * default row height as 16. Each <code>JComponent</code> subclass
132 * that has a <code>ComponentUI</code> will create the
133 * <code>ComponentUI</code> as part of its constructor. In order
134 * to provide a particular look and feel each
135 * <code>ComponentUI</code> may set properties back on the
136 * <code>JComponent</code> that created it. For example, a custom
137 * look and feel may require <code>JTable</code>s to have a row
138 * height of 24. The documented defaults are the value of a property
139 * BEFORE the <code>ComponentUI</code> has been installed. If you
140 * need a specific value for a particular property you should
141 * explicitly set it.
142 * <p>
143 * In release 1.4, the focus subsystem was rearchitected.
144 * For more information, see
145 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
146 * How to Use the Focus Subsystem</a>,
147 * a section in <em>The Java Tutorial</em>.
148 * <p>
149 * <strong>Warning:</strong> Swing is not thread safe. For more
150 * information see <a
151 * href="package-summary.html#threading">Swing's Threading
152 * Policy</a>.
153 * <p>
154 * <strong>Warning:</strong>
155 * Serialized objects of this class will not be compatible with
156 * future Swing releases. The current serialization support is
157 * appropriate for short term storage or RMI between applications running
158 * the same version of Swing. As of 1.4, support for long term storage
159 * of all JavaBeans™
160 * has been added to the <code>java.beans</code> package.
161 * Please see {@link java.beans.XMLEncoder}.
162 *
163 * @see KeyStroke
164 * @see Action
165 * @see #setBorder
166 * @see #registerKeyboardAction
167 * @see JOptionPane
168 * @see #setDebugGraphicsOptions
169 * @see #setToolTipText
170 * @see #setAutoscrolls
171 *
172 * @author Hans Muller
173 * @author Arnaud Weber
174 * @since 1.2
175 */
176 @JavaBean(defaultProperty = "UIClassID")
177 @SuppressWarnings("serial") // Same-version serialization only
178 public abstract class JComponent extends Container implements Serializable,
179 TransferHandler.HasGetTransferHandler
180 {
181 /**
182 * @see #getUIClassID
183 * @see #writeObject
184 */
185 private static final String uiClassID = "ComponentUI";
186
187 /**
188 * @see #readObject
189 */
190 private static final Hashtable<ObjectInputStream, ReadObjectCallback> readObjectCallbacks =
191 new Hashtable<ObjectInputStream, ReadObjectCallback>(1);
192
193 /**
194 * Keys to use for forward focus traversal when the JComponent is
195 * managing focus.
196 */
197 private static Set<KeyStroke> managingFocusForwardTraversalKeys;
198
199 /**
200 * Keys to use for backward focus traversal when the JComponent is
201 * managing focus.
202 */
203 private static Set<KeyStroke> managingFocusBackwardTraversalKeys;
204
205 // Following are the possible return values from getObscuredState.
206 private static final int NOT_OBSCURED = 0;
207 private static final int PARTIALLY_OBSCURED = 1;
208 private static final int COMPLETELY_OBSCURED = 2;
209
210 /**
211 * Set to true when DebugGraphics has been loaded.
212 */
213 static boolean DEBUG_GRAPHICS_LOADED;
214
215 /**
216 * Key used to look up a value from the AppContext to determine the
217 * JComponent the InputVerifier is running for. That is, if
218 * AppContext.get(INPUT_VERIFIER_SOURCE_KEY) returns non-null, it
219 * indicates the EDT is calling into the InputVerifier from the
220 * returned component.
221 */
222 private static final Object INPUT_VERIFIER_SOURCE_KEY =
223 new StringBuilder("InputVerifierSourceKey");
224
225 /* The following fields support set methods for the corresponding
226 * java.awt.Component properties.
227 */
228 private boolean isAlignmentXSet;
229 private float alignmentX;
230 private boolean isAlignmentYSet;
231 private float alignmentY;
232
233 /**
234 * Backing store for JComponent properties and listeners
235 */
236
237 /** The look and feel delegate for this component. */
238 protected transient ComponentUI ui;
239 /** A list of event listeners for this component. */
240 protected EventListenerList listenerList = new EventListenerList();
241
242 private transient ArrayTable clientProperties;
243 private VetoableChangeSupport vetoableChangeSupport;
244 /**
245 * Whether or not autoscroll has been enabled.
246 */
247 private boolean autoscrolls;
248 private Border border;
249 private int flags;
250
251 /* Input verifier for this component */
252 private InputVerifier inputVerifier = null;
253
254 private boolean verifyInputWhenFocusTarget = true;
255
256 /**
257 * Set in <code>_paintImmediately</code>.
258 * Will indicate the child that initiated the painting operation.
259 * If <code>paintingChild</code> is opaque, no need to paint
260 * any child components after <code>paintingChild</code>.
261 * Test used in <code>paintChildren</code>.
262 */
263 transient Component paintingChild;
264
265 /**
266 * Constant used for <code>registerKeyboardAction</code> that
267 * means that the command should be invoked when
268 * the component has the focus.
269 */
270 public static final int WHEN_FOCUSED = 0;
271
272 /**
273 * Constant used for <code>registerKeyboardAction</code> that
274 * means that the command should be invoked when the receiving
275 * component is an ancestor of the focused component or is
276 * itself the focused component.
277 */
278 public static final int WHEN_ANCESTOR_OF_FOCUSED_COMPONENT = 1;
279
280 /**
281 * Constant used for <code>registerKeyboardAction</code> that
282 * means that the command should be invoked when
283 * the receiving component is in the window that has the focus
284 * or is itself the focused component.
285 */
286 public static final int WHEN_IN_FOCUSED_WINDOW = 2;
287
288 /**
289 * Constant used by some of the APIs to mean that no condition is defined.
290 */
291 public static final int UNDEFINED_CONDITION = -1;
292
293 /**
294 * The key used by <code>JComponent</code> to access keyboard bindings.
295 */
296 private static final String KEYBOARD_BINDINGS_KEY = "_KeyboardBindings";
297
298 /**
299 * An array of <code>KeyStroke</code>s used for
300 * <code>WHEN_IN_FOCUSED_WINDOW</code> are stashed
301 * in the client properties under this string.
302 */
303 private static final String WHEN_IN_FOCUSED_WINDOW_BINDINGS = "_WhenInFocusedWindow";
304
305 /**
306 * The comment to display when the cursor is over the component,
307 * also known as a "value tip", "flyover help", or "flyover label".
308 */
309 public static final String TOOL_TIP_TEXT_KEY = "ToolTipText";
310
311 private static final String NEXT_FOCUS = "nextFocus";
312
313 /**
314 * <code>JPopupMenu</code> assigned to this component
315 * and all of its children
316 */
317 private JPopupMenu popupMenu;
318
319 /** Private flags **/
320 private static final int IS_DOUBLE_BUFFERED = 0;
321 private static final int ANCESTOR_USING_BUFFER = 1;
322 private static final int IS_PAINTING_TILE = 2;
323 private static final int IS_OPAQUE = 3;
324 private static final int KEY_EVENTS_ENABLED = 4;
325 private static final int FOCUS_INPUTMAP_CREATED = 5;
326 private static final int ANCESTOR_INPUTMAP_CREATED = 6;
327 private static final int WIF_INPUTMAP_CREATED = 7;
328 private static final int ACTIONMAP_CREATED = 8;
329 private static final int CREATED_DOUBLE_BUFFER = 9;
330 // bit 10 is free
331 private static final int IS_PRINTING = 11;
332 private static final int IS_PRINTING_ALL = 12;
333 private static final int IS_REPAINTING = 13;
334 /** Bits 14-21 are used to handle nested writeObject calls. **/
335 private static final int WRITE_OBJ_COUNTER_FIRST = 14;
336 private static final int RESERVED_1 = 15;
337 private static final int RESERVED_2 = 16;
338 private static final int RESERVED_3 = 17;
339 private static final int RESERVED_4 = 18;
340 private static final int RESERVED_5 = 19;
341 private static final int RESERVED_6 = 20;
342 private static final int WRITE_OBJ_COUNTER_LAST = 21;
343
344 private static final int REQUEST_FOCUS_DISABLED = 22;
345 private static final int INHERITS_POPUP_MENU = 23;
346 private static final int OPAQUE_SET = 24;
347 private static final int AUTOSCROLLS_SET = 25;
348 private static final int FOCUS_TRAVERSAL_KEYS_FORWARD_SET = 26;
349 private static final int FOCUS_TRAVERSAL_KEYS_BACKWARD_SET = 27;
350
351 private transient AtomicBoolean revalidateRunnableScheduled = new AtomicBoolean(false);
352
353 /**
354 * Temporary rectangles.
355 */
356 private static java.util.List<Rectangle> tempRectangles = new java.util.ArrayList<Rectangle>(11);
357
358 /** Used for <code>WHEN_FOCUSED</code> bindings. */
359 private InputMap focusInputMap;
360 /** Used for <code>WHEN_ANCESTOR_OF_FOCUSED_COMPONENT</code> bindings. */
361 private InputMap ancestorInputMap;
362 /** Used for <code>WHEN_IN_FOCUSED_KEY</code> bindings. */
363 private ComponentInputMap windowInputMap;
364
365 /** ActionMap. */
366 private ActionMap actionMap;
367
368 /** Key used to store the default locale in an AppContext **/
369 private static final String defaultLocale = "JComponent.defaultLocale";
370
371 private static Component componentObtainingGraphicsFrom;
372 private static Object componentObtainingGraphicsFromLock = new
373 StringBuilder("componentObtainingGraphicsFrom");
374
375 /**
376 * AA text hints.
377 */
378 private transient Object aaHint;
379 private transient Object lcdRenderingHint;
380
381 static Graphics safelyGetGraphics(Component c) {
382 return safelyGetGraphics(c, SwingUtilities.getRoot(c));
383 }
384
385 static Graphics safelyGetGraphics(Component c, Component root) {
386 synchronized(componentObtainingGraphicsFromLock) {
387 componentObtainingGraphicsFrom = root;
388 Graphics g = c.getGraphics();
389 componentObtainingGraphicsFrom = null;
390 return g;
391 }
392 }
393
394 static void getGraphicsInvoked(Component root) {
395 if (!JComponent.isComponentObtainingGraphicsFrom(root)) {
396 JRootPane rootPane = ((RootPaneContainer)root).getRootPane();
397 if (rootPane != null) {
398 rootPane.disableTrueDoubleBuffering();
399 }
400 }
401 }
402
403
404 /**
405 * Returns true if {@code c} is the component the graphics is being
406 * requested of. This is intended for use when getGraphics is invoked.
407 */
408 private static boolean isComponentObtainingGraphicsFrom(Component c) {
409 synchronized(componentObtainingGraphicsFromLock) {
410 return (componentObtainingGraphicsFrom == c);
411 }
412 }
413
414 /**
415 * Returns the Set of <code>KeyStroke</code>s to use if the component
416 * is managing focus for forward focus traversal.
417 */
418 static Set<KeyStroke> getManagingFocusForwardTraversalKeys() {
419 synchronized(JComponent.class) {
420 if (managingFocusForwardTraversalKeys == null) {
421 managingFocusForwardTraversalKeys = new HashSet<KeyStroke>(1);
422 managingFocusForwardTraversalKeys.add(
423 KeyStroke.getKeyStroke(KeyEvent.VK_TAB,
424 InputEvent.CTRL_MASK));
425 }
426 }
427 return managingFocusForwardTraversalKeys;
428 }
429
430 /**
431 * Returns the Set of <code>KeyStroke</code>s to use if the component
432 * is managing focus for backward focus traversal.
433 */
434 static Set<KeyStroke> getManagingFocusBackwardTraversalKeys() {
435 synchronized(JComponent.class) {
436 if (managingFocusBackwardTraversalKeys == null) {
437 managingFocusBackwardTraversalKeys = new HashSet<KeyStroke>(1);
438 managingFocusBackwardTraversalKeys.add(
439 KeyStroke.getKeyStroke(KeyEvent.VK_TAB,
440 InputEvent.SHIFT_MASK |
441 InputEvent.CTRL_MASK));
442 }
443 }
444 return managingFocusBackwardTraversalKeys;
445 }
446
447 private static Rectangle fetchRectangle() {
448 synchronized(tempRectangles) {
449 Rectangle rect;
450 int size = tempRectangles.size();
451 if (size > 0) {
452 rect = tempRectangles.remove(size - 1);
453 }
454 else {
455 rect = new Rectangle(0, 0, 0, 0);
456 }
457 return rect;
458 }
459 }
460
461 private static void recycleRectangle(Rectangle rect) {
462 synchronized(tempRectangles) {
463 tempRectangles.add(rect);
464 }
465 }
466
467 /**
468 * Sets whether or not <code>getComponentPopupMenu</code> should delegate
469 * to the parent if this component does not have a <code>JPopupMenu</code>
470 * assigned to it.
471 * <p>
472 * The default value for this is false, but some <code>JComponent</code>
473 * subclasses that are implemented as a number of <code>JComponent</code>s
474 * may set this to true.
475 * <p>
476 * This is a bound property.
477 *
478 * @param value whether or not the JPopupMenu is inherited
479 * @see #setComponentPopupMenu
480 * @since 1.5
481 */
482 @BeanProperty(description
483 = "Whether or not the JPopupMenu is inherited")
484 public void setInheritsPopupMenu(boolean value) {
485 boolean oldValue = getFlag(INHERITS_POPUP_MENU);
486 setFlag(INHERITS_POPUP_MENU, value);
487 firePropertyChange("inheritsPopupMenu", oldValue, value);
488 }
489
490 /**
491 * Returns true if the JPopupMenu should be inherited from the parent.
492 *
493 * @return true if the JPopupMenu should be inherited from the parent
494 * @see #setComponentPopupMenu
495 * @since 1.5
496 */
497 public boolean getInheritsPopupMenu() {
498 return getFlag(INHERITS_POPUP_MENU);
499 }
500
501 /**
502 * Sets the <code>JPopupMenu</code> for this <code>JComponent</code>.
503 * The UI is responsible for registering bindings and adding the necessary
504 * listeners such that the <code>JPopupMenu</code> will be shown at
505 * the appropriate time. When the <code>JPopupMenu</code> is shown
506 * depends upon the look and feel: some may show it on a mouse event,
507 * some may enable a key binding.
508 * <p>
509 * If <code>popup</code> is null, and <code>getInheritsPopupMenu</code>
510 * returns true, then <code>getComponentPopupMenu</code> will be delegated
511 * to the parent. This provides for a way to make all child components
512 * inherit the popupmenu of the parent.
513 * <p>
514 * This is a bound property.
515 *
516 * @param popup - the popup that will be assigned to this component
517 * may be null
518 * @see #getComponentPopupMenu
519 * @since 1.5
520 */
521 @BeanProperty(preferred = true, description
522 = "Popup to show")
523 public void setComponentPopupMenu(JPopupMenu popup) {
524 if(popup != null) {
525 enableEvents(AWTEvent.MOUSE_EVENT_MASK);
526 }
527 JPopupMenu oldPopup = this.popupMenu;
528 this.popupMenu = popup;
529 firePropertyChange("componentPopupMenu", oldPopup, popup);
530 }
531
532 /**
533 * Returns <code>JPopupMenu</code> that assigned for this component.
534 * If this component does not have a <code>JPopupMenu</code> assigned
535 * to it and <code>getInheritsPopupMenu</code> is true, this
536 * will return <code>getParent().getComponentPopupMenu()</code> (assuming
537 * the parent is valid.)
538 *
539 * @return <code>JPopupMenu</code> assigned for this component
540 * or <code>null</code> if no popup assigned
541 * @see #setComponentPopupMenu
542 * @since 1.5
543 */
544 public JPopupMenu getComponentPopupMenu() {
545
546 if(!getInheritsPopupMenu()) {
547 return popupMenu;
548 }
549
550 if(popupMenu == null) {
551 // Search parents for its popup
552 Container parent = getParent();
553 while (parent != null) {
554 if(parent instanceof JComponent) {
555 return ((JComponent)parent).getComponentPopupMenu();
556 }
557 if(parent instanceof Window ||
558 parent instanceof Applet) {
559 // Reached toplevel, break and return null
560 break;
561 }
562 parent = parent.getParent();
563 }
564 return null;
565 }
566
567 return popupMenu;
568 }
569
570 /**
571 * Default <code>JComponent</code> constructor. This constructor does
572 * very little initialization beyond calling the <code>Container</code>
573 * constructor. For example, the initial layout manager is
574 * <code>null</code>. It does, however, set the component's locale
575 * property to the value returned by
576 * <code>JComponent.getDefaultLocale</code>.
577 *
578 * @see #getDefaultLocale
579 */
580 public JComponent() {
581 super();
582 // We enable key events on all JComponents so that accessibility
583 // bindings will work everywhere. This is a partial fix to BugID
584 // 4282211.
585 enableEvents(AWTEvent.KEY_EVENT_MASK);
586 if (isManagingFocus()) {
587 LookAndFeel.installProperty(this,
588 "focusTraversalKeysForward",
589 getManagingFocusForwardTraversalKeys());
590 LookAndFeel.installProperty(this,
591 "focusTraversalKeysBackward",
592 getManagingFocusBackwardTraversalKeys());
593 }
594
595 super.setLocale( JComponent.getDefaultLocale() );
596 }
597
598
599 /**
600 * Resets the UI property to a value from the current look and feel.
601 * <code>JComponent</code> subclasses must override this method
602 * like this:
603 * <pre>
604 * public void updateUI() {
605 * setUI((SliderUI)UIManager.getUI(this);
606 * }
607 * </pre>
608 *
609 * @see #setUI
610 * @see UIManager#getLookAndFeel
611 * @see UIManager#getUI
612 */
613 public void updateUI() {}
614
615 /**
616 * Returns the look and feel delegate that renders this component.
617 *
618 * @return the {@code ComponentUI} object that renders this component
619 * @since 9
620 */
621 @Transient
622 public ComponentUI getUI() {
623 return ui;
624 }
625
626 /**
627 * Sets the look and feel delegate for this component.
628 * <code>JComponent</code> subclasses generally override this method
629 * to narrow the argument type. For example, in <code>JSlider</code>:
630 * <pre>
631 * public void setUI(SliderUI newUI) {
632 * super.setUI(newUI);
633 * }
634 * </pre>
635 * <p>
636 * Additionally <code>JComponent</code> subclasses must provide a
637 * <code>getUI</code> method that returns the correct type. For example:
638 * <pre>
639 * public SliderUI getUI() {
640 * return (SliderUI)ui;
641 * }
642 * </pre>
643 *
644 * @param newUI the new UI delegate
645 * @see #updateUI
646 * @see UIManager#getLookAndFeel
647 * @see UIManager#getUI
648 */
649 @BeanProperty(hidden = true, visualUpdate = true, description
650 = "The component's look and feel delegate.")
651 protected void setUI(ComponentUI newUI) {
652 /* We do not check that the UI instance is different
653 * before allowing the switch in order to enable the
654 * same UI instance *with different default settings*
655 * to be installed.
656 */
657
658 uninstallUIAndProperties();
659
660 // aaText shouldn't persist between look and feels, reset it.
661 aaHint = UIManager.getDefaults().get(
662 RenderingHints.KEY_TEXT_ANTIALIASING);
663 lcdRenderingHint = UIManager.getDefaults().get(
664 RenderingHints.KEY_TEXT_LCD_CONTRAST);
665 ComponentUI oldUI = ui;
666 ui = newUI;
667 if (ui != null) {
668 ui.installUI(this);
669 }
670
671 firePropertyChange("UI", oldUI, newUI);
672 revalidate();
673 repaint();
674 }
675
676 /**
677 * Uninstalls the UI, if any, and any client properties designated
678 * as being specific to the installed UI - instances of
679 * {@code UIClientPropertyKey}.
680 */
681 private void uninstallUIAndProperties() {
682 if (ui != null) {
683 ui.uninstallUI(this);
684 //clean UIClientPropertyKeys from client properties
685 if (clientProperties != null) {
686 synchronized(clientProperties) {
687 Object[] clientPropertyKeys =
688 clientProperties.getKeys(null);
689 if (clientPropertyKeys != null) {
690 for (Object key : clientPropertyKeys) {
691 if (key instanceof UIClientPropertyKey) {
692 putClientProperty(key, null);
693 }
694 }
695 }
696 }
697 }
698 }
699 }
700
701 /**
702 * Returns the <code>UIDefaults</code> key used to
703 * look up the name of the <code>swing.plaf.ComponentUI</code>
704 * class that defines the look and feel
705 * for this component. Most applications will never need to
706 * call this method. Subclasses of <code>JComponent</code> that support
707 * pluggable look and feel should override this method to
708 * return a <code>UIDefaults</code> key that maps to the
709 * <code>ComponentUI</code> subclass that defines their look and feel.
710 *
711 * @return the <code>UIDefaults</code> key for a
712 * <code>ComponentUI</code> subclass
713 * @see UIDefaults#getUI
714 */
715 @BeanProperty(bound = false, expert = true, description
716 = "UIClassID")
717 public String getUIClassID() {
718 return uiClassID;
719 }
720
721
722 /**
723 * Returns the graphics object used to paint this component.
724 * If <code>DebugGraphics</code> is turned on we create a new
725 * <code>DebugGraphics</code> object if necessary.
726 * Otherwise we just configure the
727 * specified graphics object's foreground and font.
728 *
729 * @param g the original <code>Graphics</code> object
730 * @return a <code>Graphics</code> object configured for this component
731 */
732 protected Graphics getComponentGraphics(Graphics g) {
733 Graphics componentGraphics = g;
734 if (ui != null && DEBUG_GRAPHICS_LOADED) {
735 if ((DebugGraphics.debugComponentCount() != 0) &&
736 (shouldDebugGraphics() != 0) &&
737 !(g instanceof DebugGraphics)) {
738 componentGraphics = new DebugGraphics(g,this);
739 }
740 }
741 componentGraphics.setColor(getForeground());
742 componentGraphics.setFont(getFont());
743
744 return componentGraphics;
745 }
746
747
748 /**
749 * Calls the UI delegate's paint method, if the UI delegate
750 * is non-<code>null</code>. We pass the delegate a copy of the
751 * <code>Graphics</code> object to protect the rest of the
752 * paint code from irrevocable changes
753 * (for example, <code>Graphics.translate</code>).
754 * <p>
755 * If you override this in a subclass you should not make permanent
756 * changes to the passed in <code>Graphics</code>. For example, you
757 * should not alter the clip <code>Rectangle</code> or modify the
758 * transform. If you need to do these operations you may find it
759 * easier to create a new <code>Graphics</code> from the passed in
760 * <code>Graphics</code> and manipulate it. Further, if you do not
761 * invoker super's implementation you must honor the opaque property,
762 * that is
763 * if this component is opaque, you must completely fill in the background
764 * in a non-opaque color. If you do not honor the opaque property you
765 * will likely see visual artifacts.
766 * <p>
767 * The passed in <code>Graphics</code> object might
768 * have a transform other than the identify transform
769 * installed on it. In this case, you might get
770 * unexpected results if you cumulatively apply
771 * another transform.
772 *
773 * @param g the <code>Graphics</code> object to protect
774 * @see #paint
775 * @see ComponentUI
776 */
777 protected void paintComponent(Graphics g) {
778 if (ui != null) {
779 Graphics scratchGraphics = (g == null) ? null : g.create();
780 try {
781 ui.update(scratchGraphics, this);
782 }
783 finally {
784 scratchGraphics.dispose();
785 }
786 }
787 }
788
789 /**
790 * Paints this component's children.
791 * If <code>shouldUseBuffer</code> is true,
792 * no component ancestor has a buffer and
793 * the component children can use a buffer if they have one.
794 * Otherwise, one ancestor has a buffer currently in use and children
795 * should not use a buffer to paint.
796 * @param g the <code>Graphics</code> context in which to paint
797 * @see #paint
798 * @see java.awt.Container#paint
799 */
800 protected void paintChildren(Graphics g) {
801 Graphics sg = g;
802
803 synchronized(getTreeLock()) {
804 int i = getComponentCount() - 1;
805 if (i < 0) {
806 return;
807 }
808 // If we are only to paint to a specific child, determine
809 // its index.
810 if (paintingChild != null &&
811 (paintingChild instanceof JComponent) &&
812 paintingChild.isOpaque()) {
813 for (; i >= 0; i--) {
814 if (getComponent(i) == paintingChild){
815 break;
816 }
817 }
818 }
819 Rectangle tmpRect = fetchRectangle();
820 boolean checkSiblings = (!isOptimizedDrawingEnabled() &&
821 checkIfChildObscuredBySibling());
822 Rectangle clipBounds = null;
823 if (checkSiblings) {
824 clipBounds = sg.getClipBounds();
825 if (clipBounds == null) {
826 clipBounds = new Rectangle(0, 0, getWidth(),
827 getHeight());
828 }
829 }
830 boolean printing = getFlag(IS_PRINTING);
831 final Window window = SwingUtilities.getWindowAncestor(this);
832 final boolean isWindowOpaque = window == null || window.isOpaque();
833 for (; i >= 0 ; i--) {
834 Component comp = getComponent(i);
835 if (comp == null) {
836 continue;
837 }
838
839 final boolean isJComponent = comp instanceof JComponent;
840
841 // Enable painting of heavyweights in non-opaque windows.
842 // See 6884960
843 if ((!isWindowOpaque || isJComponent ||
844 isLightweightComponent(comp)) && comp.isVisible())
845 {
846 Rectangle cr;
847
848 cr = comp.getBounds(tmpRect);
849
850 boolean hitClip = g.hitClip(cr.x, cr.y, cr.width,
851 cr.height);
852
853 if (hitClip) {
854 if (checkSiblings && i > 0) {
855 int x = cr.x;
856 int y = cr.y;
857 int width = cr.width;
858 int height = cr.height;
859 SwingUtilities.computeIntersection
860 (clipBounds.x, clipBounds.y,
861 clipBounds.width, clipBounds.height, cr);
862
863 if(getObscuredState(i, cr.x, cr.y, cr.width,
864 cr.height) == COMPLETELY_OBSCURED) {
865 continue;
866 }
867 cr.x = x;
868 cr.y = y;
869 cr.width = width;
870 cr.height = height;
871 }
872 Graphics cg = sg.create(cr.x, cr.y, cr.width,
873 cr.height);
874 cg.setColor(comp.getForeground());
875 cg.setFont(comp.getFont());
876 boolean shouldSetFlagBack = false;
877 try {
878 if(isJComponent) {
879 if(getFlag(ANCESTOR_USING_BUFFER)) {
880 ((JComponent)comp).setFlag(
881 ANCESTOR_USING_BUFFER,true);
882 shouldSetFlagBack = true;
883 }
884 if(getFlag(IS_PAINTING_TILE)) {
885 ((JComponent)comp).setFlag(
886 IS_PAINTING_TILE,true);
887 shouldSetFlagBack = true;
888 }
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 } else {
901 // The component is either lightweight, or
902 // heavyweight in a non-opaque window
903 if (!printing) {
904 comp.paint(cg);
905 }
906 else {
907 if (!getFlag(IS_PRINTING_ALL)) {
908 comp.print(cg);
909 }
910 else {
911 comp.printAll(cg);
912 }
913 }
914 }
915 } finally {
916 cg.dispose();
917 if(shouldSetFlagBack) {
918 ((JComponent)comp).setFlag(
919 ANCESTOR_USING_BUFFER,false);
920 ((JComponent)comp).setFlag(
921 IS_PAINTING_TILE,false);
922 }
923 }
924 }
925 }
926
927 }
928 recycleRectangle(tmpRect);
929 }
930 }
931
932 /**
933 * Paints the component's border.
934 * <p>
935 * If you override this in a subclass you should not make permanent
936 * changes to the passed in <code>Graphics</code>. For example, you
937 * should not alter the clip <code>Rectangle</code> or modify the
938 * transform. If you need to do these operations you may find it
939 * easier to create a new <code>Graphics</code> from the passed in
940 * <code>Graphics</code> and manipulate it.
941 *
942 * @param g the <code>Graphics</code> context in which to paint
943 *
944 * @see #paint
945 * @see #setBorder
946 */
947 protected void paintBorder(Graphics g) {
948 Border border = getBorder();
949 if (border != null) {
950 border.paintBorder(this, g, 0, 0, getWidth(), getHeight());
951 }
952 }
953
954
955 /**
956 * Calls <code>paint</code>. Doesn't clear the background but see
957 * <code>ComponentUI.update</code>, which is called by
958 * <code>paintComponent</code>.
959 *
960 * @param g the <code>Graphics</code> context in which to paint
961 * @see #paint
962 * @see #paintComponent
963 * @see javax.swing.plaf.ComponentUI
964 */
965 public void update(Graphics g) {
966 paint(g);
967 }
968
969
970 /**
971 * Invoked by Swing to draw components.
972 * Applications should not invoke <code>paint</code> directly,
973 * but should instead use the <code>repaint</code> method to
974 * schedule the component for redrawing.
975 * <p>
976 * This method actually delegates the work of painting to three
977 * protected methods: <code>paintComponent</code>,
978 * <code>paintBorder</code>,
979 * and <code>paintChildren</code>. They're called in the order
980 * listed to ensure that children appear on top of component itself.
981 * Generally speaking, the component and its children should not
982 * paint in the insets area allocated to the border. Subclasses can
983 * just override this method, as always. A subclass that just
984 * wants to specialize the UI (look and feel) delegate's
985 * <code>paint</code> method should just override
986 * <code>paintComponent</code>.
987 *
988 * @param g the <code>Graphics</code> context in which to paint
989 * @see #paintComponent
990 * @see #paintBorder
991 * @see #paintChildren
992 * @see #getComponentGraphics
993 * @see #repaint
994 */
995 public void paint(Graphics g) {
996 boolean shouldClearPaintFlags = false;
997
998 if ((getWidth() <= 0) || (getHeight() <= 0)) {
999 return;
1000 }
1001
1002 Graphics componentGraphics = getComponentGraphics(g);
1003 Graphics co = componentGraphics.create();
1004 try {
1005 RepaintManager repaintManager = RepaintManager.currentManager(this);
1006 Rectangle clipRect = co.getClipBounds();
1007 int clipX;
1008 int clipY;
1009 int clipW;
1010 int clipH;
1011 if (clipRect == null) {
1012 clipX = clipY = 0;
1013 clipW = getWidth();
1014 clipH = getHeight();
1015 }
1016 else {
1017 clipX = clipRect.x;
1018 clipY = clipRect.y;
1019 clipW = clipRect.width;
1020 clipH = clipRect.height;
1021 }
1022
1023 if(clipW > getWidth()) {
1024 clipW = getWidth();
1025 }
1026 if(clipH > getHeight()) {
1027 clipH = getHeight();
1028 }
1029
1030 if(getParent() != null && !(getParent() instanceof JComponent)) {
1031 adjustPaintFlags();
1032 shouldClearPaintFlags = true;
1033 }
1034
1035 int bw,bh;
1036 boolean printing = getFlag(IS_PRINTING);
1037 if (!printing && repaintManager.isDoubleBufferingEnabled() &&
1038 !getFlag(ANCESTOR_USING_BUFFER) && isDoubleBuffered() &&
1039 (getFlag(IS_REPAINTING) || repaintManager.isPainting()))
1040 {
1041 repaintManager.beginPaint();
1042 try {
1043 repaintManager.paint(this, this, co, clipX, clipY, clipW,
1044 clipH);
1045 } finally {
1046 repaintManager.endPaint();
1047 }
1048 }
1049 else {
1050 // Will ocassionaly happen in 1.2, especially when printing.
1051 if (clipRect == null) {
1052 co.setClip(clipX, clipY, clipW, clipH);
1053 }
1054
1055 if (!rectangleIsObscured(clipX,clipY,clipW,clipH)) {
1056 if (!printing) {
1057 paintComponent(co);
1058 paintBorder(co);
1059 }
1060 else {
1061 printComponent(co);
1062 printBorder(co);
1063 }
1064 }
1065 if (!printing) {
1066 paintChildren(co);
1067 }
1068 else {
1069 printChildren(co);
1070 }
1071 }
1072 } finally {
1073 co.dispose();
1074 if(shouldClearPaintFlags) {
1075 setFlag(ANCESTOR_USING_BUFFER,false);
1076 setFlag(IS_PAINTING_TILE,false);
1077 setFlag(IS_PRINTING,false);
1078 setFlag(IS_PRINTING_ALL,false);
1079 }
1080 }
1081 }
1082
1083 // paint forcing use of the double buffer. This is used for historical
1084 // reasons: JViewport, when scrolling, previously directly invoked paint
1085 // while turning off double buffering at the RepaintManager level, this
1086 // codes simulates that.
1087 void paintForceDoubleBuffered(Graphics g) {
1088 RepaintManager rm = RepaintManager.currentManager(this);
1089 Rectangle clip = g.getClipBounds();
1090 rm.beginPaint();
1091 setFlag(IS_REPAINTING, true);
1092 try {
1093 rm.paint(this, this, g, clip.x, clip.y, clip.width, clip.height);
1094 } finally {
1095 rm.endPaint();
1096 setFlag(IS_REPAINTING, false);
1097 }
1098 }
1099
1100 /**
1101 * Returns true if this component, or any of its ancestors, are in
1102 * the processing of painting.
1103 */
1104 boolean isPainting() {
1105 Container component = this;
1106 while (component != null) {
1107 if (component instanceof JComponent &&
1108 ((JComponent)component).getFlag(ANCESTOR_USING_BUFFER)) {
1109 return true;
1110 }
1111 component = component.getParent();
1112 }
1113 return false;
1114 }
1115
1116 private void adjustPaintFlags() {
1117 JComponent jparent;
1118 Container parent;
1119 for(parent = getParent() ; parent != null ; parent =
1120 parent.getParent()) {
1121 if(parent instanceof JComponent) {
1122 jparent = (JComponent) parent;
1123 if(jparent.getFlag(ANCESTOR_USING_BUFFER))
1124 setFlag(ANCESTOR_USING_BUFFER, true);
1125 if(jparent.getFlag(IS_PAINTING_TILE))
1126 setFlag(IS_PAINTING_TILE, true);
1127 if(jparent.getFlag(IS_PRINTING))
1128 setFlag(IS_PRINTING, true);
1129 if(jparent.getFlag(IS_PRINTING_ALL))
1130 setFlag(IS_PRINTING_ALL, true);
1131 break;
1132 }
1133 }
1134 }
1135
1136 /**
1137 * Invoke this method to print the component. This method invokes
1138 * <code>print</code> on the component.
1139 *
1140 * @param g the <code>Graphics</code> context in which to paint
1141 * @see #print
1142 * @see #printComponent
1143 * @see #printBorder
1144 * @see #printChildren
1145 */
1146 public void printAll(Graphics g) {
1147 setFlag(IS_PRINTING_ALL, true);
1148 try {
1149 print(g);
1150 }
1151 finally {
1152 setFlag(IS_PRINTING_ALL, false);
1153 }
1154 }
1155
1156 /**
1157 * Invoke this method to print the component to the specified
1158 * <code>Graphics</code>. This method will result in invocations
1159 * of <code>printComponent</code>, <code>printBorder</code> and
1160 * <code>printChildren</code>. It is recommended that you override
1161 * one of the previously mentioned methods rather than this one if
1162 * your intention is to customize the way printing looks. However,
1163 * it can be useful to override this method should you want to prepare
1164 * state before invoking the superclass behavior. As an example,
1165 * if you wanted to change the component's background color before
1166 * printing, you could do the following:
1167 * <pre>
1168 * public void print(Graphics g) {
1169 * Color orig = getBackground();
1170 * setBackground(Color.WHITE);
1171 *
1172 * // wrap in try/finally so that we always restore the state
1173 * try {
1174 * super.print(g);
1175 * } finally {
1176 * setBackground(orig);
1177 * }
1178 * }
1179 * </pre>
1180 * <p>
1181 * Alternatively, or for components that delegate painting to other objects,
1182 * you can query during painting whether or not the component is in the
1183 * midst of a print operation. The <code>isPaintingForPrint</code> method provides
1184 * this ability and its return value will be changed by this method: to
1185 * <code>true</code> immediately before rendering and to <code>false</code>
1186 * immediately after. With each change a property change event is fired on
1187 * this component with the name <code>"paintingForPrint"</code>.
1188 * <p>
1189 * This method sets the component's state such that the double buffer
1190 * will not be used: painting will be done directly on the passed in
1191 * <code>Graphics</code>.
1192 *
1193 * @param g the <code>Graphics</code> context in which to paint
1194 * @see #printComponent
1195 * @see #printBorder
1196 * @see #printChildren
1197 * @see #isPaintingForPrint
1198 */
1199 public void print(Graphics g) {
1200 setFlag(IS_PRINTING, true);
1201 firePropertyChange("paintingForPrint", false, true);
1202 try {
1203 paint(g);
1204 }
1205 finally {
1206 setFlag(IS_PRINTING, false);
1207 firePropertyChange("paintingForPrint", true, false);
1208 }
1209 }
1210
1211 /**
1212 * This is invoked during a printing operation. This is implemented to
1213 * invoke <code>paintComponent</code> on the component. Override this
1214 * if you wish to add special painting behavior when printing.
1215 *
1216 * @param g the <code>Graphics</code> context in which to paint
1217 * @see #print
1218 * @since 1.3
1219 */
1220 protected void printComponent(Graphics g) {
1221 paintComponent(g);
1222 }
1223
1224 /**
1225 * Prints this component's children. This is implemented to invoke
1226 * <code>paintChildren</code> on the component. Override this if you
1227 * wish to print the children differently than painting.
1228 *
1229 * @param g the <code>Graphics</code> context in which to paint
1230 * @see #print
1231 * @since 1.3
1232 */
1233 protected void printChildren(Graphics g) {
1234 paintChildren(g);
1235 }
1236
1237 /**
1238 * Prints the component's border. This is implemented to invoke
1239 * <code>paintBorder</code> on the component. Override this if you
1240 * wish to print the border differently that it is painted.
1241 *
1242 * @param g the <code>Graphics</code> context in which to paint
1243 * @see #print
1244 * @since 1.3
1245 */
1246 protected void printBorder(Graphics g) {
1247 paintBorder(g);
1248 }
1249
1250 /**
1251 * Returns true if the component is currently painting a tile.
1252 * If this method returns true, paint will be called again for another
1253 * tile. This method returns false if you are not painting a tile or
1254 * if the last tile is painted.
1255 * Use this method to keep some state you might need between tiles.
1256 *
1257 * @return true if the component is currently painting a tile,
1258 * false otherwise
1259 */
1260 @BeanProperty(bound = false)
1261 public boolean isPaintingTile() {
1262 return getFlag(IS_PAINTING_TILE);
1263 }
1264
1265 /**
1266 * Returns <code>true</code> if the current painting operation on this
1267 * component is part of a <code>print</code> operation. This method is
1268 * useful when you want to customize what you print versus what you show
1269 * on the screen.
1270 * <p>
1271 * You can detect changes in the value of this property by listening for
1272 * property change events on this component with name
1273 * <code>"paintingForPrint"</code>.
1274 * <p>
1275 * Note: This method provides complimentary functionality to that provided
1276 * by other high level Swing printing APIs. However, it deals strictly with
1277 * painting and should not be confused as providing information on higher
1278 * level print processes. For example, a {@link javax.swing.JTable#print()}
1279 * operation doesn't necessarily result in a continuous rendering of the
1280 * full component, and the return value of this method can change multiple
1281 * times during that operation. It is even possible for the component to be
1282 * painted to the screen while the printing process is ongoing. In such a
1283 * case, the return value of this method is <code>true</code> when, and only
1284 * when, the table is being painted as part of the printing process.
1285 *
1286 * @return true if the current painting operation on this component
1287 * is part of a print operation
1288 * @see #print
1289 * @since 1.6
1290 */
1291 @BeanProperty(bound = false)
1292 public final boolean isPaintingForPrint() {
1293 return getFlag(IS_PRINTING);
1294 }
1295
1296 /**
1297 * In release 1.4, the focus subsystem was rearchitected.
1298 * For more information, see
1299 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
1300 * How to Use the Focus Subsystem</a>,
1301 * a section in <em>The Java Tutorial</em>.
1302 * <p>
1303 * Changes this <code>JComponent</code>'s focus traversal keys to
1304 * CTRL+TAB and CTRL+SHIFT+TAB. Also prevents
1305 * <code>SortingFocusTraversalPolicy</code> from considering descendants
1306 * of this JComponent when computing a focus traversal cycle.
1307 *
1308 * @return false
1309 * @see java.awt.Component#setFocusTraversalKeys
1310 * @see SortingFocusTraversalPolicy
1311 * @deprecated As of 1.4, replaced by
1312 * <code>Component.setFocusTraversalKeys(int, Set)</code> and
1313 * <code>Container.setFocusCycleRoot(boolean)</code>.
1314 */
1315 @Deprecated
1316 @BeanProperty(bound = false)
1317 public boolean isManagingFocus() {
1318 return false;
1319 }
1320
1321 private void registerNextFocusableComponent() {
1322 registerNextFocusableComponent(getNextFocusableComponent());
1323 }
1324
1325 private void registerNextFocusableComponent(Component
1326 nextFocusableComponent) {
1327 if (nextFocusableComponent == null) {
1328 return;
1329 }
1330
1331 Container nearestRoot =
1332 (isFocusCycleRoot()) ? this : getFocusCycleRootAncestor();
1333 FocusTraversalPolicy policy = nearestRoot.getFocusTraversalPolicy();
1334 if (!(policy instanceof LegacyGlueFocusTraversalPolicy)) {
1335 policy = new LegacyGlueFocusTraversalPolicy(policy);
1336 nearestRoot.setFocusTraversalPolicy(policy);
1337 }
1338 ((LegacyGlueFocusTraversalPolicy)policy).
1339 setNextFocusableComponent(this, nextFocusableComponent);
1340 }
1341
1342 private void deregisterNextFocusableComponent() {
1343 Component nextFocusableComponent = getNextFocusableComponent();
1344 if (nextFocusableComponent == null) {
1345 return;
1346 }
1347
1348 Container nearestRoot =
1349 (isFocusCycleRoot()) ? this : getFocusCycleRootAncestor();
1350 if (nearestRoot == null) {
1351 return;
1352 }
1353 FocusTraversalPolicy policy = nearestRoot.getFocusTraversalPolicy();
1354 if (policy instanceof LegacyGlueFocusTraversalPolicy) {
1355 ((LegacyGlueFocusTraversalPolicy)policy).
1356 unsetNextFocusableComponent(this, nextFocusableComponent);
1357 }
1358 }
1359
1360 /**
1361 * In release 1.4, the focus subsystem was rearchitected.
1362 * For more information, see
1363 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
1364 * How to Use the Focus Subsystem</a>,
1365 * a section in <em>The Java Tutorial</em>.
1366 * <p>
1367 * Overrides the default <code>FocusTraversalPolicy</code> for this
1368 * <code>JComponent</code>'s focus traversal cycle by unconditionally
1369 * setting the specified <code>Component</code> as the next
1370 * <code>Component</code> in the cycle, and this <code>JComponent</code>
1371 * as the specified <code>Component</code>'s previous
1372 * <code>Component</code> in the cycle.
1373 *
1374 * @param aComponent the <code>Component</code> that should follow this
1375 * <code>JComponent</code> in the focus traversal cycle
1376 *
1377 * @see #getNextFocusableComponent
1378 * @see java.awt.FocusTraversalPolicy
1379 * @deprecated As of 1.4, replaced by <code>FocusTraversalPolicy</code>
1380 */
1381 @Deprecated
1382 public void setNextFocusableComponent(Component aComponent) {
1383 boolean displayable = isDisplayable();
1384 if (displayable) {
1385 deregisterNextFocusableComponent();
1386 }
1387 putClientProperty(NEXT_FOCUS, aComponent);
1388 if (displayable) {
1389 registerNextFocusableComponent(aComponent);
1390 }
1391 }
1392
1393 /**
1394 * In release 1.4, the focus subsystem was rearchitected.
1395 * For more information, see
1396 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
1397 * How to Use the Focus Subsystem</a>,
1398 * a section in <em>The Java Tutorial</em>.
1399 * <p>
1400 * Returns the <code>Component</code> set by a prior call to
1401 * <code>setNextFocusableComponent(Component)</code> on this
1402 * <code>JComponent</code>.
1403 *
1404 * @return the <code>Component</code> that will follow this
1405 * <code>JComponent</code> in the focus traversal cycle, or
1406 * <code>null</code> if none has been explicitly specified
1407 *
1408 * @see #setNextFocusableComponent
1409 * @deprecated As of 1.4, replaced by <code>FocusTraversalPolicy</code>.
1410 */
1411 @Deprecated
1412 public Component getNextFocusableComponent() {
1413 return (Component)getClientProperty(NEXT_FOCUS);
1414 }
1415
1416 /**
1417 * Provides a hint as to whether or not this <code>JComponent</code>
1418 * should get focus. This is only a hint, and it is up to consumers that
1419 * are requesting focus to honor this property. This is typically honored
1420 * for mouse operations, but not keyboard operations. For example, look
1421 * and feels could verify this property is true before requesting focus
1422 * during a mouse operation. This would often times be used if you did
1423 * not want a mouse press on a <code>JComponent</code> to steal focus,
1424 * but did want the <code>JComponent</code> to be traversable via the
1425 * keyboard. If you do not want this <code>JComponent</code> focusable at
1426 * all, use the <code>setFocusable</code> method instead.
1427 * <p>
1428 * Please see
1429 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
1430 * How to Use the Focus Subsystem</a>,
1431 * a section in <em>The Java Tutorial</em>,
1432 * for more information.
1433 *
1434 * @param requestFocusEnabled indicates whether you want this
1435 * <code>JComponent</code> to be focusable or not
1436 * @see <a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a>
1437 * @see java.awt.Component#setFocusable
1438 */
1439 public void setRequestFocusEnabled(boolean requestFocusEnabled) {
1440 setFlag(REQUEST_FOCUS_DISABLED, !requestFocusEnabled);
1441 }
1442
1443 /**
1444 * Returns <code>true</code> if this <code>JComponent</code> should
1445 * get focus; otherwise returns <code>false</code>.
1446 * <p>
1447 * Please see
1448 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
1449 * How to Use the Focus Subsystem</a>,
1450 * a section in <em>The Java Tutorial</em>,
1451 * for more information.
1452 *
1453 * @return <code>true</code> if this component should get focus,
1454 * otherwise returns <code>false</code>
1455 * @see #setRequestFocusEnabled
1456 * @see <a href="../../java/awt/doc-files/FocusSpec.html">Focus
1457 * Specification</a>
1458 * @see java.awt.Component#isFocusable
1459 */
1460 public boolean isRequestFocusEnabled() {
1461 return !getFlag(REQUEST_FOCUS_DISABLED);
1462 }
1463
1464 /**
1465 * Requests that this <code>Component</code> gets the input focus.
1466 * Refer to {@link java.awt.Component#requestFocus()
1467 * Component.requestFocus()} for a complete description of
1468 * this method.
1469 * <p>
1470 * Note that the use of this method is discouraged because
1471 * its behavior is platform dependent. Instead we recommend the
1472 * use of {@link #requestFocusInWindow() requestFocusInWindow()}.
1473 * If you would like more information on focus, see
1474 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
1475 * How to Use the Focus Subsystem</a>,
1476 * a section in <em>The Java Tutorial</em>.
1477 *
1478 * @see java.awt.Component#requestFocusInWindow()
1479 * @see java.awt.Component#requestFocusInWindow(boolean)
1480 * @since 1.4
1481 */
1482 public void requestFocus() {
1483 super.requestFocus();
1484 }
1485
1486 /**
1487 * Requests that this <code>Component</code> gets the input focus.
1488 * Refer to {@link java.awt.Component#requestFocus(boolean)
1489 * Component.requestFocus(boolean)} for a complete description of
1490 * this method.
1491 * <p>
1492 * Note that the use of this method is discouraged because
1493 * its behavior is platform dependent. Instead we recommend the
1494 * use of {@link #requestFocusInWindow(boolean)
1495 * requestFocusInWindow(boolean)}.
1496 * If you would like more information on focus, see
1497 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
1498 * How to Use the Focus Subsystem</a>,
1499 * a section in <em>The Java Tutorial</em>.
1500 *
1501 * @param temporary boolean indicating if the focus change is temporary
1502 * @return <code>false</code> if the focus change request is guaranteed to
1503 * fail; <code>true</code> if it is likely to succeed
1504 * @see java.awt.Component#requestFocusInWindow()
1505 * @see java.awt.Component#requestFocusInWindow(boolean)
1506 * @since 1.4
1507 */
1508 public boolean requestFocus(boolean temporary) {
1509 return super.requestFocus(temporary);
1510 }
1511
1512 /**
1513 * Requests that this <code>Component</code> gets the input focus.
1514 * Refer to {@link java.awt.Component#requestFocusInWindow()
1515 * Component.requestFocusInWindow()} for a complete description of
1516 * this method.
1517 * <p>
1518 * If you would like more information on focus, see
1519 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
1520 * How to Use the Focus Subsystem</a>,
1521 * a section in <em>The Java Tutorial</em>.
1522 *
1523 * @return <code>false</code> if the focus change request is guaranteed to
1524 * fail; <code>true</code> if it is likely to succeed
1525 * @see java.awt.Component#requestFocusInWindow()
1526 * @see java.awt.Component#requestFocusInWindow(boolean)
1527 * @since 1.4
1528 */
1529 public boolean requestFocusInWindow() {
1530 return super.requestFocusInWindow();
1531 }
1532
1533 /**
1534 * Requests that this <code>Component</code> gets the input focus.
1535 * Refer to {@link java.awt.Component#requestFocusInWindow(boolean)
1536 * Component.requestFocusInWindow(boolean)} for a complete description of
1537 * this method.
1538 * <p>
1539 * If you would like more information on focus, see
1540 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
1541 * How to Use the Focus Subsystem</a>,
1542 * a section in <em>The Java Tutorial</em>.
1543 *
1544 * @param temporary boolean indicating if the focus change is temporary
1545 * @return <code>false</code> if the focus change request is guaranteed to
1546 * fail; <code>true</code> if it is likely to succeed
1547 * @see java.awt.Component#requestFocusInWindow()
1548 * @see java.awt.Component#requestFocusInWindow(boolean)
1549 * @since 1.4
1550 */
1551 protected boolean requestFocusInWindow(boolean temporary) {
1552 return super.requestFocusInWindow(temporary);
1553 }
1554
1555 /**
1556 * Requests that this Component get the input focus, and that this
1557 * Component's top-level ancestor become the focused Window. This component
1558 * must be displayable, visible, and focusable for the request to be
1559 * granted.
1560 * <p>
1561 * This method is intended for use by focus implementations. Client code
1562 * should not use this method; instead, it should use
1563 * <code>requestFocusInWindow()</code>.
1564 *
1565 * @see #requestFocusInWindow()
1566 */
1567 public void grabFocus() {
1568 requestFocus();
1569 }
1570
1571 /**
1572 * Sets the value to indicate whether input verifier for the
1573 * current focus owner will be called before this component requests
1574 * focus. The default is true. Set to false on components such as a
1575 * Cancel button or a scrollbar, which should activate even if the
1576 * input in the current focus owner is not "passed" by the input
1577 * verifier for that component.
1578 *
1579 * @param verifyInputWhenFocusTarget value for the
1580 * <code>verifyInputWhenFocusTarget</code> property
1581 * @see InputVerifier
1582 * @see #setInputVerifier
1583 * @see #getInputVerifier
1584 * @see #getVerifyInputWhenFocusTarget
1585 *
1586 * @since 1.3
1587 */
1588 @BeanProperty(description
1589 = "Whether the Component verifies input before accepting focus.")
1590 public void setVerifyInputWhenFocusTarget(boolean
1591 verifyInputWhenFocusTarget) {
1592 boolean oldVerifyInputWhenFocusTarget =
1593 this.verifyInputWhenFocusTarget;
1594 this.verifyInputWhenFocusTarget = verifyInputWhenFocusTarget;
1595 firePropertyChange("verifyInputWhenFocusTarget",
1596 oldVerifyInputWhenFocusTarget,
1597 verifyInputWhenFocusTarget);
1598 }
1599
1600 /**
1601 * Returns the value that indicates whether the input verifier for the
1602 * current focus owner will be called before this component requests
1603 * focus.
1604 *
1605 * @return value of the <code>verifyInputWhenFocusTarget</code> property
1606 *
1607 * @see InputVerifier
1608 * @see #setInputVerifier
1609 * @see #getInputVerifier
1610 * @see #setVerifyInputWhenFocusTarget
1611 *
1612 * @since 1.3
1613 */
1614 public boolean getVerifyInputWhenFocusTarget() {
1615 return verifyInputWhenFocusTarget;
1616 }
1617
1618
1619 /**
1620 * Gets the <code>FontMetrics</code> for the specified <code>Font</code>.
1621 *
1622 * @param font the font for which font metrics is to be
1623 * obtained
1624 * @return the font metrics for <code>font</code>
1625 * @throws NullPointerException if <code>font</code> is null
1626 * @since 1.5
1627 */
1628 public FontMetrics getFontMetrics(Font font) {
1629 return SwingUtilities2.getFontMetrics(this, font);
1630 }
1631
1632
1633 /**
1634 * Sets the preferred size of this component.
1635 * If <code>preferredSize</code> is <code>null</code>, the UI will
1636 * be asked for the preferred size.
1637 */
1638 @BeanProperty(preferred = true, description
1639 = "The preferred size of the component.")
1640 public void setPreferredSize(Dimension preferredSize) {
1641 super.setPreferredSize(preferredSize);
1642 }
1643
1644
1645 /**
1646 * If the <code>preferredSize</code> has been set to a
1647 * non-<code>null</code> value just returns it.
1648 * If the UI delegate's <code>getPreferredSize</code>
1649 * method returns a non <code>null</code> value then return that;
1650 * otherwise defer to the component's layout manager.
1651 *
1652 * @return the value of the <code>preferredSize</code> property
1653 * @see #setPreferredSize
1654 * @see ComponentUI
1655 */
1656 @Transient
1657 public Dimension getPreferredSize() {
1658 if (isPreferredSizeSet()) {
1659 return super.getPreferredSize();
1660 }
1661 Dimension size = null;
1662 if (ui != null) {
1663 size = ui.getPreferredSize(this);
1664 }
1665 return (size != null) ? size : super.getPreferredSize();
1666 }
1667
1668
1669 /**
1670 * Sets the maximum size of this component to a constant
1671 * value. Subsequent calls to <code>getMaximumSize</code> will always
1672 * return this value; the component's UI will not be asked
1673 * to compute it. Setting the maximum size to <code>null</code>
1674 * restores the default behavior.
1675 *
1676 * @param maximumSize a <code>Dimension</code> containing the
1677 * desired maximum allowable size
1678 * @see #getMaximumSize
1679 */
1680 @BeanProperty(description
1681 = "The maximum size of the component.")
1682 public void setMaximumSize(Dimension maximumSize) {
1683 super.setMaximumSize(maximumSize);
1684 }
1685
1686
1687 /**
1688 * If the maximum size has been set to a non-<code>null</code> value
1689 * just returns it. If the UI delegate's <code>getMaximumSize</code>
1690 * method returns a non-<code>null</code> value then return that;
1691 * otherwise defer to the component's layout manager.
1692 *
1693 * @return the value of the <code>maximumSize</code> property
1694 * @see #setMaximumSize
1695 * @see ComponentUI
1696 */
1697 @Transient
1698 public Dimension getMaximumSize() {
1699 if (isMaximumSizeSet()) {
1700 return super.getMaximumSize();
1701 }
1702 Dimension size = null;
1703 if (ui != null) {
1704 size = ui.getMaximumSize(this);
1705 }
1706 return (size != null) ? size : super.getMaximumSize();
1707 }
1708
1709
1710 /**
1711 * Sets the minimum size of this component to a constant
1712 * value. Subsequent calls to <code>getMinimumSize</code> will always
1713 * return this value; the component's UI will not be asked
1714 * to compute it. Setting the minimum size to <code>null</code>
1715 * restores the default behavior.
1716 *
1717 * @param minimumSize the new minimum size of this component
1718 * @see #getMinimumSize
1719 */
1720 @BeanProperty(description
1721 = "The minimum size of the component.")
1722 public void setMinimumSize(Dimension minimumSize) {
1723 super.setMinimumSize(minimumSize);
1724 }
1725
1726 /**
1727 * If the minimum size has been set to a non-<code>null</code> value
1728 * just returns it. If the UI delegate's <code>getMinimumSize</code>
1729 * method returns a non-<code>null</code> value then return that; otherwise
1730 * defer to the component's layout manager.
1731 *
1732 * @return the value of the <code>minimumSize</code> property
1733 * @see #setMinimumSize
1734 * @see ComponentUI
1735 */
1736 @Transient
1737 public Dimension getMinimumSize() {
1738 if (isMinimumSizeSet()) {
1739 return super.getMinimumSize();
1740 }
1741 Dimension size = null;
1742 if (ui != null) {
1743 size = ui.getMinimumSize(this);
1744 }
1745 return (size != null) ? size : super.getMinimumSize();
1746 }
1747
1748 /**
1749 * Gives the UI delegate an opportunity to define the precise
1750 * shape of this component for the sake of mouse processing.
1751 *
1752 * @return true if this component logically contains x,y
1753 * @see java.awt.Component#contains(int, int)
1754 * @see ComponentUI
1755 */
1756 public boolean contains(int x, int y) {
1757 return (ui != null) ? ui.contains(this, x, y) : super.contains(x, y);
1758 }
1759
1760 /**
1761 * Sets the border of this component. The <code>Border</code> object is
1762 * responsible for defining the insets for the component
1763 * (overriding any insets set directly on the component) and
1764 * for optionally rendering any border decorations within the
1765 * bounds of those insets. Borders should be used (rather
1766 * than insets) for creating both decorative and non-decorative
1767 * (such as margins and padding) regions for a swing component.
1768 * Compound borders can be used to nest multiple borders within a
1769 * single component.
1770 * <p>
1771 * Although technically you can set the border on any object
1772 * that inherits from <code>JComponent</code>, the look and
1773 * feel implementation of many standard Swing components
1774 * doesn't work well with user-set borders. In general,
1775 * when you want to set a border on a standard Swing
1776 * component other than <code>JPanel</code> or <code>JLabel</code>,
1777 * we recommend that you put the component in a <code>JPanel</code>
1778 * and set the border on the <code>JPanel</code>.
1779 * <p>
1780 * This is a bound property.
1781 *
1782 * @param border the border to be rendered for this component
1783 * @see Border
1784 * @see CompoundBorder
1785 */
1786 @BeanProperty(preferred = true, visualUpdate = true, description
1787 = "The component's border.")
1788 public void setBorder(Border border) {
1789 Border oldBorder = this.border;
1790
1791 this.border = border;
1792 firePropertyChange("border", oldBorder, border);
1793 if (border != oldBorder) {
1794 if (border == null || oldBorder == null ||
1795 !(border.getBorderInsets(this).equals(oldBorder.getBorderInsets(this)))) {
1796 revalidate();
1797 }
1798 repaint();
1799 }
1800 }
1801
1802 /**
1803 * Returns the border of this component or <code>null</code> if no
1804 * border is currently set.
1805 *
1806 * @return the border object for this component
1807 * @see #setBorder
1808 */
1809 public Border getBorder() {
1810 return border;
1811 }
1812
1813 /**
1814 * If a border has been set on this component, returns the
1815 * border's insets; otherwise calls <code>super.getInsets</code>.
1816 *
1817 * @return the value of the insets property
1818 * @see #setBorder
1819 */
1820 @BeanProperty(expert = true)
1821 public Insets getInsets() {
1822 if (border != null) {
1823 return border.getBorderInsets(this);
1824 }
1825 return super.getInsets();
1826 }
1827
1828 /**
1829 * Returns an <code>Insets</code> object containing this component's inset
1830 * values. The passed-in <code>Insets</code> object will be reused
1831 * if possible.
1832 * Calling methods cannot assume that the same object will be returned,
1833 * however. All existing values within this object are overwritten.
1834 * If <code>insets</code> is null, this will allocate a new one.
1835 *
1836 * @param insets the <code>Insets</code> object, which can be reused
1837 * @return the <code>Insets</code> object
1838 * @see #getInsets
1839 */
1840 public Insets getInsets(Insets insets) {
1841 if (insets == null) {
1842 insets = new Insets(0, 0, 0, 0);
1843 }
1844 if (border != null) {
1845 if (border instanceof AbstractBorder) {
1846 return ((AbstractBorder)border).getBorderInsets(this, insets);
1847 } else {
1848 // Can't reuse border insets because the Border interface
1849 // can't be enhanced.
1850 return border.getBorderInsets(this);
1851 }
1852 } else {
1853 // super.getInsets() always returns an Insets object with
1854 // all of its value zeroed. No need for a new object here.
1855 insets.left = insets.top = insets.right = insets.bottom = 0;
1856 return insets;
1857 }
1858 }
1859
1860 /**
1861 * Overrides <code>Container.getAlignmentY</code> to return
1862 * the vertical alignment.
1863 *
1864 * @return the value of the <code>alignmentY</code> property
1865 * @see #setAlignmentY
1866 * @see java.awt.Component#getAlignmentY
1867 */
1868 public float getAlignmentY() {
1869 if (isAlignmentYSet) {
1870 return alignmentY;
1871 }
1872 return super.getAlignmentY();
1873 }
1874
1875 /**
1876 * Sets the vertical alignment.
1877 *
1878 * @param alignmentY the new vertical alignment
1879 * @see #getAlignmentY
1880 */
1881 @BeanProperty(description
1882 = "The preferred vertical alignment of the component.")
1883 public void setAlignmentY(float alignmentY) {
1884 this.alignmentY = validateAlignment(alignmentY);
1885 isAlignmentYSet = true;
1886 }
1887
1888
1889 /**
1890 * Overrides <code>Container.getAlignmentX</code> to return
1891 * the horizontal alignment.
1892 *
1893 * @return the value of the <code>alignmentX</code> property
1894 * @see #setAlignmentX
1895 * @see java.awt.Component#getAlignmentX
1896 */
1897 public float getAlignmentX() {
1898 if (isAlignmentXSet) {
1899 return alignmentX;
1900 }
1901 return super.getAlignmentX();
1902 }
1903
1904 /**
1905 * Sets the horizontal alignment.
1906 *
1907 * @param alignmentX the new horizontal alignment
1908 * @see #getAlignmentX
1909 */
1910 @BeanProperty(description
1911 = "The preferred horizontal alignment of the component.")
1912 public void setAlignmentX(float alignmentX) {
1913 this.alignmentX = validateAlignment(alignmentX);
1914 isAlignmentXSet = true;
1915 }
1916
1917 private float validateAlignment(float alignment) {
1918 return alignment > 1.0f ? 1.0f : alignment < 0.0f ? 0.0f : alignment;
1919 }
1920
1921 /**
1922 * Sets the input verifier for this component.
1923 *
1924 * @param inputVerifier the new input verifier
1925 * @since 1.3
1926 * @see InputVerifier
1927 */
1928 @BeanProperty(description
1929 = "The component's input verifier.")
1930 public void setInputVerifier(InputVerifier inputVerifier) {
1931 InputVerifier oldInputVerifier = (InputVerifier)getClientProperty(
1932 JComponent_INPUT_VERIFIER);
1933 putClientProperty(JComponent_INPUT_VERIFIER, inputVerifier);
1934 firePropertyChange("inputVerifier", oldInputVerifier, inputVerifier);
1935 }
1936
1937 /**
1938 * Returns the input verifier for this component.
1939 *
1940 * @return the <code>inputVerifier</code> property
1941 * @since 1.3
1942 * @see InputVerifier
1943 */
1944 public InputVerifier getInputVerifier() {
1945 return (InputVerifier)getClientProperty(JComponent_INPUT_VERIFIER);
1946 }
1947
1948 /**
1949 * Returns this component's graphics context, which lets you draw
1950 * on a component. Use this method to get a <code>Graphics</code> object and
1951 * then invoke operations on that object to draw on the component.
1952 * @return this components graphics context
1953 */
1954 @BeanProperty(bound = false)
1955 public Graphics getGraphics() {
1956 if (DEBUG_GRAPHICS_LOADED && shouldDebugGraphics() != 0) {
1957 DebugGraphics graphics = new DebugGraphics(super.getGraphics(),
1958 this);
1959 return graphics;
1960 }
1961 return super.getGraphics();
1962 }
1963
1964
1965 /** Enables or disables diagnostic information about every graphics
1966 * operation performed within the component or one of its children.
1967 *
1968 * @param debugOptions determines how the component should display
1969 * the information; one of the following options:
1970 * <ul>
1971 * <li>DebugGraphics.LOG_OPTION - causes a text message to be printed.
1972 * <li>DebugGraphics.FLASH_OPTION - causes the drawing to flash several
1973 * times.
1974 * <li>DebugGraphics.BUFFERED_OPTION - creates an
1975 * <code>ExternalWindow</code> that displays the operations
1976 * performed on the View's offscreen buffer.
1977 * <li>DebugGraphics.NONE_OPTION disables debugging.
1978 * <li>A value of 0 causes no changes to the debugging options.
1979 * </ul>
1980 * <code>debugOptions</code> is bitwise OR'd into the current value
1981 */
1982 @BeanProperty(bound = false, preferred = true, enumerationValues = {
1983 "DebugGraphics.NONE_OPTION",
1984 "DebugGraphics.LOG_OPTION",
1985 "DebugGraphics.FLASH_OPTION",
1986 "DebugGraphics.BUFFERED_OPTION"}, description
1987 = "Diagnostic options for graphics operations.")
1988 public void setDebugGraphicsOptions(int debugOptions) {
1989 DebugGraphics.setDebugOptions(this, debugOptions);
1990 }
1991
1992 /** Returns the state of graphics debugging.
1993 *
1994 * @return a bitwise OR'd flag of zero or more of the following options:
1995 * <ul>
1996 * <li>DebugGraphics.LOG_OPTION - causes a text message to be printed.
1997 * <li>DebugGraphics.FLASH_OPTION - causes the drawing to flash several
1998 * times.
1999 * <li>DebugGraphics.BUFFERED_OPTION - creates an
2000 * <code>ExternalWindow</code> that displays the operations
2001 * performed on the View's offscreen buffer.
2002 * <li>DebugGraphics.NONE_OPTION disables debugging.
2003 * <li>A value of 0 causes no changes to the debugging options.
2004 * </ul>
2005 * @see #setDebugGraphicsOptions
2006 */
2007 public int getDebugGraphicsOptions() {
2008 return DebugGraphics.getDebugOptions(this);
2009 }
2010
2011
2012 /**
2013 * Returns true if debug information is enabled for this
2014 * <code>JComponent</code> or one of its parents.
2015 */
2016 int shouldDebugGraphics() {
2017 return DebugGraphics.shouldComponentDebug(this);
2018 }
2019
2020 /**
2021 * This method is now obsolete, please use a combination of
2022 * <code>getActionMap()</code> and <code>getInputMap()</code> for
2023 * similar behavior. For example, to bind the <code>KeyStroke</code>
2024 * <code>aKeyStroke</code> to the <code>Action</code> <code>anAction</code>
2025 * now use:
2026 * <pre>
2027 * component.getInputMap().put(aKeyStroke, aCommand);
2028 * component.getActionMap().put(aCommmand, anAction);
2029 * </pre>
2030 * The above assumes you want the binding to be applicable for
2031 * <code>WHEN_FOCUSED</code>. To register bindings for other focus
2032 * states use the <code>getInputMap</code> method that takes an integer.
2033 * <p>
2034 * Register a new keyboard action.
2035 * <code>anAction</code> will be invoked if a key event matching
2036 * <code>aKeyStroke</code> occurs and <code>aCondition</code> is verified.
2037 * The <code>KeyStroke</code> object defines a
2038 * particular combination of a keyboard key and one or more modifiers
2039 * (alt, shift, ctrl, meta).
2040 * <p>
2041 * The <code>aCommand</code> will be set in the delivered event if
2042 * specified.
2043 * <p>
2044 * The <code>aCondition</code> can be one of:
2045 * <blockquote>
2046 * <DL>
2047 * <DT>WHEN_FOCUSED
2048 * <DD>The action will be invoked only when the keystroke occurs
2049 * while the component has the focus.
2050 * <DT>WHEN_IN_FOCUSED_WINDOW
2051 * <DD>The action will be invoked when the keystroke occurs while
2052 * the component has the focus or if the component is in the
2053 * window that has the focus. Note that the component need not
2054 * be an immediate descendent of the window -- it can be
2055 * anywhere in the window's containment hierarchy. In other
2056 * words, whenever <em>any</em> component in the window has the focus,
2057 * the action registered with this component is invoked.
2058 * <DT>WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
2059 * <DD>The action will be invoked when the keystroke occurs while the
2060 * component has the focus or if the component is an ancestor of
2061 * the component that has the focus.
2062 * </DL>
2063 * </blockquote>
2064 * <p>
2065 * The combination of keystrokes and conditions lets you define high
2066 * level (semantic) action events for a specified keystroke+modifier
2067 * combination (using the KeyStroke class) and direct to a parent or
2068 * child of a component that has the focus, or to the component itself.
2069 * In other words, in any hierarchical structure of components, an
2070 * arbitrary key-combination can be immediately directed to the
2071 * appropriate component in the hierarchy, and cause a specific method
2072 * to be invoked (usually by way of adapter objects).
2073 * <p>
2074 * If an action has already been registered for the receiving
2075 * container, with the same charCode and the same modifiers,
2076 * <code>anAction</code> will replace the action.
2077 *
2078 * @param anAction the <code>Action</code> to be registered
2079 * @param aCommand the command to be set in the delivered event
2080 * @param aKeyStroke the <code>KeyStroke</code> to bind to the action
2081 * @param aCondition the condition that needs to be met, see above
2082 * @see KeyStroke
2083 */
2084 public void registerKeyboardAction(ActionListener anAction,String aCommand,KeyStroke aKeyStroke,int aCondition) {
2085
2086 InputMap inputMap = getInputMap(aCondition, true);
2087
2088 if (inputMap != null) {
2089 ActionMap actionMap = getActionMap(true);
2090 ActionStandin action = new ActionStandin(anAction, aCommand);
2091 inputMap.put(aKeyStroke, action);
2092 if (actionMap != null) {
2093 actionMap.put(action, action);
2094 }
2095 }
2096 }
2097
2098 /**
2099 * Registers any bound <code>WHEN_IN_FOCUSED_WINDOW</code> actions with
2100 * the <code>KeyboardManager</code>. If <code>onlyIfNew</code>
2101 * is true only actions that haven't been registered are pushed
2102 * to the <code>KeyboardManager</code>;
2103 * otherwise all actions are pushed to the <code>KeyboardManager</code>.
2104 *
2105 * @param onlyIfNew if true, only actions that haven't been registered
2106 * are pushed to the <code>KeyboardManager</code>
2107 */
2108 private void registerWithKeyboardManager(boolean onlyIfNew) {
2109 InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW, false);
2110 KeyStroke[] strokes;
2111 @SuppressWarnings("unchecked")
2112 Hashtable<KeyStroke, KeyStroke> registered =
2113 (Hashtable<KeyStroke, KeyStroke>)getClientProperty
2114 (WHEN_IN_FOCUSED_WINDOW_BINDINGS);
2115
2116 if (inputMap != null) {
2117 // Push any new KeyStrokes to the KeyboardManager.
2118 strokes = inputMap.allKeys();
2119 if (strokes != null) {
2120 for (int counter = strokes.length - 1; counter >= 0;
2121 counter--) {
2122 if (!onlyIfNew || registered == null ||
2123 registered.get(strokes[counter]) == null) {
2124 registerWithKeyboardManager(strokes[counter]);
2125 }
2126 if (registered != null) {
2127 registered.remove(strokes[counter]);
2128 }
2129 }
2130 }
2131 }
2132 else {
2133 strokes = null;
2134 }
2135 // Remove any old ones.
2136 if (registered != null && registered.size() > 0) {
2137 Enumeration<KeyStroke> keys = registered.keys();
2138
2139 while (keys.hasMoreElements()) {
2140 KeyStroke ks = keys.nextElement();
2141 unregisterWithKeyboardManager(ks);
2142 }
2143 registered.clear();
2144 }
2145 // Updated the registered Hashtable.
2146 if (strokes != null && strokes.length > 0) {
2147 if (registered == null) {
2148 registered = new Hashtable<KeyStroke, KeyStroke>(strokes.length);
2149 putClientProperty(WHEN_IN_FOCUSED_WINDOW_BINDINGS, registered);
2150 }
2151 for (int counter = strokes.length - 1; counter >= 0; counter--) {
2152 registered.put(strokes[counter], strokes[counter]);
2153 }
2154 }
2155 else {
2156 putClientProperty(WHEN_IN_FOCUSED_WINDOW_BINDINGS, null);
2157 }
2158 }
2159
2160 /**
2161 * Unregisters all the previously registered
2162 * <code>WHEN_IN_FOCUSED_WINDOW</code> <code>KeyStroke</code> bindings.
2163 */
2164 private void unregisterWithKeyboardManager() {
2165 @SuppressWarnings("unchecked")
2166 Hashtable<KeyStroke, KeyStroke> registered =
2167 (Hashtable<KeyStroke, KeyStroke>)getClientProperty
2168 (WHEN_IN_FOCUSED_WINDOW_BINDINGS);
2169
2170 if (registered != null && registered.size() > 0) {
2171 Enumeration<KeyStroke> keys = registered.keys();
2172
2173 while (keys.hasMoreElements()) {
2174 KeyStroke ks = keys.nextElement();
2175 unregisterWithKeyboardManager(ks);
2176 }
2177 }
2178 putClientProperty(WHEN_IN_FOCUSED_WINDOW_BINDINGS, null);
2179 }
2180
2181 /**
2182 * Invoked from <code>ComponentInputMap</code> when its bindings change.
2183 * If <code>inputMap</code> is the current <code>windowInputMap</code>
2184 * (or a parent of the window <code>InputMap</code>)
2185 * the <code>KeyboardManager</code> is notified of the new bindings.
2186 *
2187 * @param inputMap the map containing the new bindings
2188 */
2189 void componentInputMapChanged(ComponentInputMap inputMap) {
2190 InputMap km = getInputMap(WHEN_IN_FOCUSED_WINDOW, false);
2191
2192 while (km != inputMap && km != null) {
2193 km = km.getParent();
2194 }
2195 if (km != null) {
2196 registerWithKeyboardManager(false);
2197 }
2198 }
2199
2200 private void registerWithKeyboardManager(KeyStroke aKeyStroke) {
2201 KeyboardManager.getCurrentManager().registerKeyStroke(aKeyStroke,this);
2202 }
2203
2204 private void unregisterWithKeyboardManager(KeyStroke aKeyStroke) {
2205 KeyboardManager.getCurrentManager().unregisterKeyStroke(aKeyStroke,
2206 this);
2207 }
2208
2209 /**
2210 * This method is now obsolete, please use a combination of
2211 * <code>getActionMap()</code> and <code>getInputMap()</code> for
2212 * similar behavior.
2213 *
2214 * @param anAction action to be registered to given keystroke and condition
2215 * @param aKeyStroke a {@code KeyStroke}
2216 * @param aCondition the condition to be associated with given keystroke
2217 * and action
2218 * @see #getActionMap
2219 * @see #getInputMap(int)
2220 */
2221 public void registerKeyboardAction(ActionListener anAction,KeyStroke aKeyStroke,int aCondition) {
2222 registerKeyboardAction(anAction,null,aKeyStroke,aCondition);
2223 }
2224
2225 /**
2226 * This method is now obsolete. To unregister an existing binding
2227 * you can either remove the binding from the
2228 * <code>ActionMap/InputMap</code>, or place a dummy binding the
2229 * <code>InputMap</code>. Removing the binding from the
2230 * <code>InputMap</code> allows bindings in parent <code>InputMap</code>s
2231 * to be active, whereas putting a dummy binding in the
2232 * <code>InputMap</code> effectively disables
2233 * the binding from ever happening.
2234 * <p>
2235 * Unregisters a keyboard action.
2236 * This will remove the binding from the <code>ActionMap</code>
2237 * (if it exists) as well as the <code>InputMap</code>s.
2238 *
2239 * @param aKeyStroke the keystroke for which to unregister its
2240 * keyboard action
2241 */
2242 public void unregisterKeyboardAction(KeyStroke aKeyStroke) {
2243 ActionMap am = getActionMap(false);
2244 for (int counter = 0; counter < 3; counter++) {
2245 InputMap km = getInputMap(counter, false);
2246 if (km != null) {
2247 Object actionID = km.get(aKeyStroke);
2248
2249 if (am != null && actionID != null) {
2250 am.remove(actionID);
2251 }
2252 km.remove(aKeyStroke);
2253 }
2254 }
2255 }
2256
2257 /**
2258 * Returns the <code>KeyStrokes</code> that will initiate
2259 * registered actions.
2260 *
2261 * @return an array of <code>KeyStroke</code> objects
2262 * @see #registerKeyboardAction
2263 */
2264 @BeanProperty(bound = false)
2265 public KeyStroke[] getRegisteredKeyStrokes() {
2266 int[] counts = new int[3];
2267 KeyStroke[][] strokes = new KeyStroke[3][];
2268
2269 for (int counter = 0; counter < 3; counter++) {
2270 InputMap km = getInputMap(counter, false);
2271 strokes[counter] = (km != null) ? km.allKeys() : null;
2272 counts[counter] = (strokes[counter] != null) ?
2273 strokes[counter].length : 0;
2274 }
2275 KeyStroke[] retValue = new KeyStroke[counts[0] + counts[1] +
2276 counts[2]];
2277 for (int counter = 0, last = 0; counter < 3; counter++) {
2278 if (counts[counter] > 0) {
2279 System.arraycopy(strokes[counter], 0, retValue, last,
2280 counts[counter]);
2281 last += counts[counter];
2282 }
2283 }
2284 return retValue;
2285 }
2286
2287 /**
2288 * Returns the condition that determines whether a registered action
2289 * occurs in response to the specified keystroke.
2290 * <p>
2291 * For Java 2 platform v1.3, a <code>KeyStroke</code> can be associated
2292 * with more than one condition.
2293 * For example, 'a' could be bound for the two
2294 * conditions <code>WHEN_FOCUSED</code> and
2295 * <code>WHEN_IN_FOCUSED_WINDOW</code> condition.
2296 *
2297 * @param aKeyStroke the keystroke for which to request an
2298 * action-keystroke condition
2299 * @return the action-keystroke condition
2300 */
2301 public int getConditionForKeyStroke(KeyStroke aKeyStroke) {
2302 for (int counter = 0; counter < 3; counter++) {
2303 InputMap inputMap = getInputMap(counter, false);
2304 if (inputMap != null && inputMap.get(aKeyStroke) != null) {
2305 return counter;
2306 }
2307 }
2308 return UNDEFINED_CONDITION;
2309 }
2310
2311 /**
2312 * Returns the object that will perform the action registered for a
2313 * given keystroke.
2314 *
2315 * @param aKeyStroke the keystroke for which to return a listener
2316 * @return the <code>ActionListener</code>
2317 * object invoked when the keystroke occurs
2318 */
2319 public ActionListener getActionForKeyStroke(KeyStroke aKeyStroke) {
2320 ActionMap am = getActionMap(false);
2321
2322 if (am == null) {
2323 return null;
2324 }
2325 for (int counter = 0; counter < 3; counter++) {
2326 InputMap inputMap = getInputMap(counter, false);
2327 if (inputMap != null) {
2328 Object actionBinding = inputMap.get(aKeyStroke);
2329
2330 if (actionBinding != null) {
2331 Action action = am.get(actionBinding);
2332 if (action instanceof ActionStandin) {
2333 return ((ActionStandin)action).actionListener;
2334 }
2335 return action;
2336 }
2337 }
2338 }
2339 return null;
2340 }
2341
2342 /**
2343 * Unregisters all the bindings in the first tier <code>InputMaps</code>
2344 * and <code>ActionMap</code>. This has the effect of removing any
2345 * local bindings, and allowing the bindings defined in parent
2346 * <code>InputMap/ActionMaps</code>
2347 * (the UI is usually defined in the second tier) to persist.
2348 */
2349 public void resetKeyboardActions() {
2350 // Keys
2351 for (int counter = 0; counter < 3; counter++) {
2352 InputMap inputMap = getInputMap(counter, false);
2353
2354 if (inputMap != null) {
2355 inputMap.clear();
2356 }
2357 }
2358
2359 // Actions
2360 ActionMap am = getActionMap(false);
2361
2362 if (am != null) {
2363 am.clear();
2364 }
2365 }
2366
2367 /**
2368 * Sets the <code>InputMap</code> to use under the condition
2369 * <code>condition</code> to
2370 * <code>map</code>. A <code>null</code> value implies you
2371 * do not want any bindings to be used, even from the UI. This will
2372 * not reinstall the UI <code>InputMap</code> (if there was one).
2373 * <code>condition</code> has one of the following values:
2374 * <ul>
2375 * <li><code>WHEN_IN_FOCUSED_WINDOW</code>
2376 * <li><code>WHEN_FOCUSED</code>
2377 * <li><code>WHEN_ANCESTOR_OF_FOCUSED_COMPONENT</code>
2378 * </ul>
2379 * If <code>condition</code> is <code>WHEN_IN_FOCUSED_WINDOW</code>
2380 * and <code>map</code> is not a <code>ComponentInputMap</code>, an
2381 * <code>IllegalArgumentException</code> will be thrown.
2382 * Similarly, if <code>condition</code> is not one of the values
2383 * listed, an <code>IllegalArgumentException</code> will be thrown.
2384 *
2385 * @param condition one of the values listed above
2386 * @param map the <code>InputMap</code> to use for the given condition
2387 * @exception IllegalArgumentException if <code>condition</code> is
2388 * <code>WHEN_IN_FOCUSED_WINDOW</code> and <code>map</code>
2389 * is not an instance of <code>ComponentInputMap</code>; or
2390 * if <code>condition</code> is not one of the legal values
2391 * specified above
2392 * @since 1.3
2393 */
2394 public final void setInputMap(int condition, InputMap map) {
2395 switch (condition) {
2396 case WHEN_IN_FOCUSED_WINDOW:
2397 if (map != null && !(map instanceof ComponentInputMap)) {
2398 throw new IllegalArgumentException("WHEN_IN_FOCUSED_WINDOW InputMaps must be of type ComponentInputMap");
2399 }
2400 windowInputMap = (ComponentInputMap)map;
2401 setFlag(WIF_INPUTMAP_CREATED, true);
2402 registerWithKeyboardManager(false);
2403 break;
2404 case WHEN_ANCESTOR_OF_FOCUSED_COMPONENT:
2405 ancestorInputMap = map;
2406 setFlag(ANCESTOR_INPUTMAP_CREATED, true);
2407 break;
2408 case WHEN_FOCUSED:
2409 focusInputMap = map;
2410 setFlag(FOCUS_INPUTMAP_CREATED, true);
2411 break;
2412 default:
2413 throw new IllegalArgumentException("condition must be one of JComponent.WHEN_IN_FOCUSED_WINDOW, JComponent.WHEN_FOCUSED or JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT");
2414 }
2415 }
2416
2417 /**
2418 * Returns the <code>InputMap</code> that is used during
2419 * <code>condition</code>.
2420 *
2421 * @param condition one of WHEN_IN_FOCUSED_WINDOW, WHEN_FOCUSED,
2422 * WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
2423 * @return the <code>InputMap</code> for the specified
2424 * <code>condition</code>
2425 * @since 1.3
2426 */
2427 public final InputMap getInputMap(int condition) {
2428 return getInputMap(condition, true);
2429 }
2430
2431 /**
2432 * Returns the <code>InputMap</code> that is used when the
2433 * component has focus.
2434 * This is convenience method for <code>getInputMap(WHEN_FOCUSED)</code>.
2435 *
2436 * @return the <code>InputMap</code> used when the component has focus
2437 * @since 1.3
2438 */
2439 public final InputMap getInputMap() {
2440 return getInputMap(WHEN_FOCUSED, true);
2441 }
2442
2443 /**
2444 * Sets the <code>ActionMap</code> to <code>am</code>. This does not set
2445 * the parent of the <code>am</code> to be the <code>ActionMap</code>
2446 * from the UI (if there was one), it is up to the caller to have done this.
2447 *
2448 * @param am the new <code>ActionMap</code>
2449 * @since 1.3
2450 */
2451 public final void setActionMap(ActionMap am) {
2452 actionMap = am;
2453 setFlag(ACTIONMAP_CREATED, true);
2454 }
2455
2456 /**
2457 * Returns the <code>ActionMap</code> used to determine what
2458 * <code>Action</code> to fire for particular <code>KeyStroke</code>
2459 * binding. The returned <code>ActionMap</code>, unless otherwise
2460 * set, will have the <code>ActionMap</code> from the UI set as the parent.
2461 *
2462 * @return the <code>ActionMap</code> containing the key/action bindings
2463 * @since 1.3
2464 */
2465 public final ActionMap getActionMap() {
2466 return getActionMap(true);
2467 }
2468
2469 /**
2470 * Returns the <code>InputMap</code> to use for condition
2471 * <code>condition</code>. If the <code>InputMap</code> hasn't
2472 * been created, and <code>create</code> is
2473 * true, it will be created.
2474 *
2475 * @param condition one of the following values:
2476 * <ul>
2477 * <li>JComponent.FOCUS_INPUTMAP_CREATED
2478 * <li>JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
2479 * <li>JComponent.WHEN_IN_FOCUSED_WINDOW
2480 * </ul>
2481 * @param create if true, create the <code>InputMap</code> if it
2482 * is not already created
2483 * @return the <code>InputMap</code> for the given <code>condition</code>;
2484 * if <code>create</code> is false and the <code>InputMap</code>
2485 * hasn't been created, returns <code>null</code>
2486 * @exception IllegalArgumentException if <code>condition</code>
2487 * is not one of the legal values listed above
2488 */
2489 final InputMap getInputMap(int condition, boolean create) {
2490 switch (condition) {
2491 case WHEN_FOCUSED:
2492 if (getFlag(FOCUS_INPUTMAP_CREATED)) {
2493 return focusInputMap;
2494 }
2495 // Hasn't been created yet.
2496 if (create) {
2497 InputMap km = new InputMap();
2498 setInputMap(condition, km);
2499 return km;
2500 }
2501 break;
2502 case WHEN_ANCESTOR_OF_FOCUSED_COMPONENT:
2503 if (getFlag(ANCESTOR_INPUTMAP_CREATED)) {
2504 return ancestorInputMap;
2505 }
2506 // Hasn't been created yet.
2507 if (create) {
2508 InputMap km = new InputMap();
2509 setInputMap(condition, km);
2510 return km;
2511 }
2512 break;
2513 case WHEN_IN_FOCUSED_WINDOW:
2514 if (getFlag(WIF_INPUTMAP_CREATED)) {
2515 return windowInputMap;
2516 }
2517 // Hasn't been created yet.
2518 if (create) {
2519 ComponentInputMap km = new ComponentInputMap(this);
2520 setInputMap(condition, km);
2521 return km;
2522 }
2523 break;
2524 default:
2525 throw new IllegalArgumentException("condition must be one of JComponent.WHEN_IN_FOCUSED_WINDOW, JComponent.WHEN_FOCUSED or JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT");
2526 }
2527 return null;
2528 }
2529
2530 /**
2531 * Finds and returns the appropriate <code>ActionMap</code>.
2532 *
2533 * @param create if true, create the <code>ActionMap</code> if it
2534 * is not already created
2535 * @return the <code>ActionMap</code> for this component; if the
2536 * <code>create</code> flag is false and there is no
2537 * current <code>ActionMap</code>, returns <code>null</code>
2538 */
2539 final ActionMap getActionMap(boolean create) {
2540 if (getFlag(ACTIONMAP_CREATED)) {
2541 return actionMap;
2542 }
2543 // Hasn't been created.
2544 if (create) {
2545 ActionMap am = new ActionMap();
2546 setActionMap(am);
2547 return am;
2548 }
2549 return null;
2550 }
2551
2552 /**
2553 * Returns the baseline. The baseline is measured from the top of
2554 * the component. This method is primarily meant for
2555 * <code>LayoutManager</code>s to align components along their
2556 * baseline. A return value less than 0 indicates this component
2557 * does not have a reasonable baseline and that
2558 * <code>LayoutManager</code>s should not align this component on
2559 * its baseline.
2560 * <p>
2561 * This method calls into the <code>ComponentUI</code> method of the
2562 * same name. If this component does not have a <code>ComponentUI</code>
2563 * -1 will be returned. If a value >= 0 is
2564 * returned, then the component has a valid baseline for any
2565 * size >= the minimum size and <code>getBaselineResizeBehavior</code>
2566 * can be used to determine how the baseline changes with size.
2567 *
2568 * @throws IllegalArgumentException {@inheritDoc}
2569 * @see #getBaselineResizeBehavior
2570 * @see java.awt.FontMetrics
2571 * @since 1.6
2572 */
2573 public int getBaseline(int width, int height) {
2574 // check size.
2575 super.getBaseline(width, height);
2576 if (ui != null) {
2577 return ui.getBaseline(this, width, height);
2578 }
2579 return -1;
2580 }
2581
2582 /**
2583 * Returns an enum indicating how the baseline of the component
2584 * changes as the size changes. This method is primarily meant for
2585 * layout managers and GUI builders.
2586 * <p>
2587 * This method calls into the <code>ComponentUI</code> method of
2588 * the same name. If this component does not have a
2589 * <code>ComponentUI</code>
2590 * <code>BaselineResizeBehavior.OTHER</code> will be
2591 * returned. Subclasses should
2592 * never return <code>null</code>; if the baseline can not be
2593 * calculated return <code>BaselineResizeBehavior.OTHER</code>. Callers
2594 * should first ask for the baseline using
2595 * <code>getBaseline</code> and if a value >= 0 is returned use
2596 * this method. It is acceptable for this method to return a
2597 * value other than <code>BaselineResizeBehavior.OTHER</code> even if
2598 * <code>getBaseline</code> returns a value less than 0.
2599 *
2600 * @see #getBaseline(int, int)
2601 * @since 1.6
2602 */
2603 @BeanProperty(bound = false)
2604 public BaselineResizeBehavior getBaselineResizeBehavior() {
2605 if (ui != null) {
2606 return ui.getBaselineResizeBehavior(this);
2607 }
2608 return BaselineResizeBehavior.OTHER;
2609 }
2610
2611 /**
2612 * In release 1.4, the focus subsystem was rearchitected.
2613 * For more information, see
2614 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
2615 * How to Use the Focus Subsystem</a>,
2616 * a section in <em>The Java Tutorial</em>.
2617 * <p>
2618 * Requests focus on this <code>JComponent</code>'s
2619 * <code>FocusTraversalPolicy</code>'s default <code>Component</code>.
2620 * If this <code>JComponent</code> is a focus cycle root, then its
2621 * <code>FocusTraversalPolicy</code> is used. Otherwise, the
2622 * <code>FocusTraversalPolicy</code> of this <code>JComponent</code>'s
2623 * focus-cycle-root ancestor is used.
2624 *
2625 * @return true if this component can request to get the input focus,
2626 * false if it can not
2627 * @see java.awt.FocusTraversalPolicy#getDefaultComponent
2628 * @deprecated As of 1.4, replaced by
2629 * <code>FocusTraversalPolicy.getDefaultComponent(Container).requestFocus()</code>
2630 */
2631 @Deprecated
2632 public boolean requestDefaultFocus() {
2633 Container nearestRoot =
2634 (isFocusCycleRoot()) ? this : getFocusCycleRootAncestor();
2635 if (nearestRoot == null) {
2636 return false;
2637 }
2638 Component comp = nearestRoot.getFocusTraversalPolicy().
2639 getDefaultComponent(nearestRoot);
2640 if (comp != null) {
2641 comp.requestFocus();
2642 return true;
2643 } else {
2644 return false;
2645 }
2646 }
2647
2648 /**
2649 * Makes the component visible or invisible.
2650 * Overrides <code>Component.setVisible</code>.
2651 *
2652 * @param aFlag true to make the component visible; false to
2653 * make it invisible
2654 */
2655 @BeanProperty(hidden = true, visualUpdate = true)
2656 public void setVisible(boolean aFlag) {
2657 if (aFlag != isVisible()) {
2658 super.setVisible(aFlag);
2659 if (aFlag) {
2660 Container parent = getParent();
2661 if (parent != null) {
2662 Rectangle r = getBounds();
2663 parent.repaint(r.x, r.y, r.width, r.height);
2664 }
2665 revalidate();
2666 }
2667 }
2668 }
2669
2670 /**
2671 * Sets whether or not this component is enabled.
2672 * A component that is enabled may respond to user input,
2673 * while a component that is not enabled cannot respond to
2674 * user input. Some components may alter their visual
2675 * representation when they are disabled in order to
2676 * provide feedback to the user that they cannot take input.
2677 * <p>Note: Disabling a component does not disable its children.
2678 *
2679 * <p>Note: Disabling a lightweight component does not prevent it from
2680 * receiving MouseEvents.
2681 *
2682 * @param enabled true if this component should be enabled, false otherwise
2683 * @see java.awt.Component#isEnabled
2684 * @see java.awt.Component#isLightweight
2685 */
2686 @BeanProperty(expert = true, preferred = true, visualUpdate = true, description
2687 = "The enabled state of the component.")
2688 public void setEnabled(boolean enabled) {
2689 boolean oldEnabled = isEnabled();
2690 super.setEnabled(enabled);
2691 firePropertyChange("enabled", oldEnabled, enabled);
2692 if (enabled != oldEnabled) {
2693 repaint();
2694 }
2695 }
2696
2697 /**
2698 * Sets the foreground color of this component. It is up to the
2699 * look and feel to honor this property, some may choose to ignore
2700 * it.
2701 *
2702 * @param fg the desired foreground <code>Color</code>
2703 * @see java.awt.Component#getForeground
2704 */
2705 @BeanProperty(preferred = true, visualUpdate = true, description
2706 = "The foreground color of the component.")
2707 public void setForeground(Color fg) {
2708 Color oldFg = getForeground();
2709 super.setForeground(fg);
2710 if ((oldFg != null) ? !oldFg.equals(fg) : ((fg != null) && !fg.equals(oldFg))) {
2711 // foreground already bound in AWT1.2
2712 repaint();
2713 }
2714 }
2715
2716 /**
2717 * Sets the background color of this component. The background
2718 * color is used only if the component is opaque, and only
2719 * by subclasses of <code>JComponent</code> or
2720 * <code>ComponentUI</code> implementations. Direct subclasses of
2721 * <code>JComponent</code> must override
2722 * <code>paintComponent</code> to honor this property.
2723 * <p>
2724 * It is up to the look and feel to honor this property, some may
2725 * choose to ignore it.
2726 *
2727 * @param bg the desired background <code>Color</code>
2728 * @see java.awt.Component#getBackground
2729 * @see #setOpaque
2730 */
2731 @BeanProperty(preferred = true, visualUpdate = true, description
2732 = "The background color of the component.")
2733 public void setBackground(Color bg) {
2734 Color oldBg = getBackground();
2735 super.setBackground(bg);
2736 if ((oldBg != null) ? !oldBg.equals(bg) : ((bg != null) && !bg.equals(oldBg))) {
2737 // background already bound in AWT1.2
2738 repaint();
2739 }
2740 }
2741
2742 /**
2743 * Sets the font for this component.
2744 *
2745 * @param font the desired <code>Font</code> for this component
2746 * @see java.awt.Component#getFont
2747 */
2748 @BeanProperty(preferred = true, visualUpdate = true, description
2749 = "The font for the component.")
2750 public void setFont(Font font) {
2751 Font oldFont = getFont();
2752 super.setFont(font);
2753 // font already bound in AWT1.2
2754 if (font != oldFont) {
2755 revalidate();
2756 repaint();
2757 }
2758 }
2759
2760 /**
2761 * Returns the default locale used to initialize each JComponent's
2762 * locale property upon creation.
2763 *
2764 * The default locale has "AppContext" scope so that applets (and
2765 * potentially multiple lightweight applications running in a single VM)
2766 * can have their own setting. An applet can safely alter its default
2767 * locale because it will have no affect on other applets (or the browser).
2768 *
2769 * @return the default <code>Locale</code>.
2770 * @see #setDefaultLocale
2771 * @see java.awt.Component#getLocale
2772 * @see #setLocale
2773 * @since 1.4
2774 */
2775 public static Locale getDefaultLocale() {
2776 Locale l = (Locale) SwingUtilities.appContextGet(defaultLocale);
2777 if( l == null ) {
2778 //REMIND(bcb) choosing the default value is more complicated
2779 //than this.
2780 l = Locale.getDefault();
2781 JComponent.setDefaultLocale( l );
2782 }
2783 return l;
2784 }
2785
2786
2787 /**
2788 * Sets the default locale used to initialize each JComponent's locale
2789 * property upon creation. The initial value is the VM's default locale.
2790 *
2791 * The default locale has "AppContext" scope so that applets (and
2792 * potentially multiple lightweight applications running in a single VM)
2793 * can have their own setting. An applet can safely alter its default
2794 * locale because it will have no affect on other applets (or the browser).
2795 *
2796 * @param l the desired default <code>Locale</code> for new components.
2797 * @see #getDefaultLocale
2798 * @see java.awt.Component#getLocale
2799 * @see #setLocale
2800 * @since 1.4
2801 */
2802 public static void setDefaultLocale( Locale l ) {
2803 SwingUtilities.appContextPut(defaultLocale, l);
2804 }
2805
2806
2807 /**
2808 * Processes any key events that the component itself
2809 * recognizes. This is called after the focus
2810 * manager and any interested listeners have been
2811 * given a chance to steal away the event. This
2812 * method is called only if the event has not
2813 * yet been consumed. This method is called prior
2814 * to the keyboard UI logic.
2815 * <p>
2816 * This method is implemented to do nothing. Subclasses would
2817 * normally override this method if they process some
2818 * key events themselves. If the event is processed,
2819 * it should be consumed.
2820 *
2821 * @param e the event to be processed
2822 */
2823 protected void processComponentKeyEvent(KeyEvent e) {
2824 }
2825
2826 /** Overrides <code>processKeyEvent</code> to process events. **/
2827 protected void processKeyEvent(KeyEvent e) {
2828 boolean result;
2829 boolean shouldProcessKey;
2830
2831 // This gives the key event listeners a crack at the event
2832 super.processKeyEvent(e);
2833
2834 // give the component itself a crack at the event
2835 if (! e.isConsumed()) {
2836 processComponentKeyEvent(e);
2837 }
2838
2839 shouldProcessKey = KeyboardState.shouldProcess(e);
2840
2841 if(e.isConsumed()) {
2842 return;
2843 }
2844
2845 if (shouldProcessKey && processKeyBindings(e, e.getID() ==
2846 KeyEvent.KEY_PRESSED)) {
2847 e.consume();
2848 }
2849 }
2850
2851 /**
2852 * Invoked to process the key bindings for <code>ks</code> as the result
2853 * of the <code>KeyEvent</code> <code>e</code>. This obtains
2854 * the appropriate <code>InputMap</code>,
2855 * gets the binding, gets the action from the <code>ActionMap</code>,
2856 * and then (if the action is found and the component
2857 * is enabled) invokes <code>notifyAction</code> to notify the action.
2858 *
2859 * @param ks the <code>KeyStroke</code> queried
2860 * @param e the <code>KeyEvent</code>
2861 * @param condition one of the following values:
2862 * <ul>
2863 * <li>JComponent.WHEN_FOCUSED
2864 * <li>JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
2865 * <li>JComponent.WHEN_IN_FOCUSED_WINDOW
2866 * </ul>
2867 * @param pressed true if the key is pressed
2868 * @return true if there was a binding to an action, and the action
2869 * was enabled
2870 *
2871 * @since 1.3
2872 */
2873 protected boolean processKeyBinding(KeyStroke ks, KeyEvent e,
2874 int condition, boolean pressed) {
2875 InputMap map = getInputMap(condition, false);
2876 ActionMap am = getActionMap(false);
2877
2878 if(map != null && am != null && isEnabled()) {
2879 Object binding = map.get(ks);
2880 Action action = (binding == null) ? null : am.get(binding);
2881 if (action != null) {
2882 return SwingUtilities.notifyAction(action, ks, e, this,
2883 e.getModifiers());
2884 }
2885 }
2886 return false;
2887 }
2888
2889 /**
2890 * This is invoked as the result of a <code>KeyEvent</code>
2891 * that was not consumed by the <code>FocusManager</code>,
2892 * <code>KeyListeners</code>, or the component. It will first try
2893 * <code>WHEN_FOCUSED</code> bindings,
2894 * then <code>WHEN_ANCESTOR_OF_FOCUSED_COMPONENT</code> bindings,
2895 * and finally <code>WHEN_IN_FOCUSED_WINDOW</code> bindings.
2896 *
2897 * @param e the unconsumed <code>KeyEvent</code>
2898 * @param pressed true if the key is pressed
2899 * @return true if there is a key binding for <code>e</code>
2900 */
2901 boolean processKeyBindings(KeyEvent e, boolean pressed) {
2902 if (!SwingUtilities.isValidKeyEventForKeyBindings(e)) {
2903 return false;
2904 }
2905 // Get the KeyStroke
2906 // There may be two keystrokes associated with a low-level key event;
2907 // in this case a keystroke made of an extended key code has a priority.
2908 KeyStroke ks;
2909 KeyStroke ksE = null;
2910
2911 if (e.getID() == KeyEvent.KEY_TYPED) {
2912 ks = KeyStroke.getKeyStroke(e.getKeyChar());
2913 }
2914 else {
2915 ks = KeyStroke.getKeyStroke(e.getKeyCode(),e.getModifiers(),
2916 (pressed ? false:true));
2917 if (e.getKeyCode() != e.getExtendedKeyCode()) {
2918 ksE = KeyStroke.getKeyStroke(e.getExtendedKeyCode(),e.getModifiers(),
2919 (pressed ? false:true));
2920 }
2921 }
2922
2923 // Do we have a key binding for e?
2924 // If we have a binding by an extended code, use it.
2925 // If not, check for regular code binding.
2926 if(ksE != null && processKeyBinding(ksE, e, WHEN_FOCUSED, pressed)) {
2927 return true;
2928 }
2929 if(processKeyBinding(ks, e, WHEN_FOCUSED, pressed))
2930 return true;
2931
2932 /* We have no key binding. Let's try the path from our parent to the
2933 * window excluded. We store the path components so we can avoid
2934 * asking the same component twice.
2935 */
2936 Container parent = this;
2937 while (parent != null && !(parent instanceof Window) &&
2938 !(parent instanceof Applet)) {
2939 if(parent instanceof JComponent) {
2940 if(ksE != null && ((JComponent)parent).processKeyBinding(ksE, e,
2941 WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, pressed))
2942 return true;
2943 if(((JComponent)parent).processKeyBinding(ks, e,
2944 WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, pressed))
2945 return true;
2946 }
2947 // This is done so that the children of a JInternalFrame are
2948 // given precedence for WHEN_IN_FOCUSED_WINDOW bindings before
2949 // other components WHEN_IN_FOCUSED_WINDOW bindings. This also gives
2950 // more precedence to the WHEN_IN_FOCUSED_WINDOW bindings of the
2951 // JInternalFrame's children vs the
2952 // WHEN_ANCESTOR_OF_FOCUSED_COMPONENT bindings of the parents.
2953 // maybe generalize from JInternalFrame (like isFocusCycleRoot).
2954 if ((parent instanceof JInternalFrame) &&
2955 JComponent.processKeyBindingsForAllComponents(e,parent,pressed)){
2956 return true;
2957 }
2958 parent = parent.getParent();
2959 }
2960
2961 /* No components between the focused component and the window is
2962 * actually interested by the key event. Let's try the other
2963 * JComponent in this window.
2964 */
2965 if(parent != null) {
2966 return JComponent.processKeyBindingsForAllComponents(e,parent,pressed);
2967 }
2968 return false;
2969 }
2970
2971 static boolean processKeyBindingsForAllComponents(KeyEvent e,
2972 Container container, boolean pressed) {
2973 while (true) {
2974 if (KeyboardManager.getCurrentManager().fireKeyboardAction(
2975 e, pressed, container)) {
2976 return true;
2977 }
2978 if (container instanceof Popup.HeavyWeightWindow) {
2979 container = ((Window)container).getOwner();
2980 }
2981 else {
2982 return false;
2983 }
2984 }
2985 }
2986
2987 /**
2988 * Registers the text to display in a tool tip.
2989 * The text displays when the cursor lingers over the component.
2990 * <p>
2991 * See <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/tooltip.html">How to Use Tool Tips</a>
2992 * in <em>The Java Tutorial</em>
2993 * for further documentation.
2994 *
2995 * @param text the string to display; if the text is <code>null</code>,
2996 * the tool tip is turned off for this component
2997 * @see #TOOL_TIP_TEXT_KEY
2998 */
2999 @BeanProperty(bound = false, preferred = true, description
3000 = "The text to display in a tool tip.")
3001 public void setToolTipText(String text) {
3002 String oldText = getToolTipText();
3003 putClientProperty(TOOL_TIP_TEXT_KEY, text);
3004 ToolTipManager toolTipManager = ToolTipManager.sharedInstance();
3005 if (text != null) {
3006 if (oldText == null) {
3007 toolTipManager.registerComponent(this);
3008 }
3009 } else {
3010 toolTipManager.unregisterComponent(this);
3011 }
3012 }
3013
3014 /**
3015 * Returns the tooltip string that has been set with
3016 * <code>setToolTipText</code>.
3017 *
3018 * @return the text of the tool tip
3019 * @see #TOOL_TIP_TEXT_KEY
3020 */
3021 public String getToolTipText() {
3022 return (String)getClientProperty(TOOL_TIP_TEXT_KEY);
3023 }
3024
3025
3026 /**
3027 * Returns the string to be used as the tooltip for <i>event</i>.
3028 * By default this returns any string set using
3029 * <code>setToolTipText</code>. If a component provides
3030 * more extensive API to support differing tooltips at different locations,
3031 * this method should be overridden.
3032 *
3033 * @param event the {@code MouseEvent} that initiated the
3034 * {@code ToolTip} display
3035 * @return a string containing the tooltip
3036 */
3037 public String getToolTipText(MouseEvent event) {
3038 return getToolTipText();
3039 }
3040
3041 /**
3042 * Returns the tooltip location in this component's coordinate system.
3043 * If <code>null</code> is returned, Swing will choose a location.
3044 * The default implementation returns <code>null</code>.
3045 *
3046 * @param event the <code>MouseEvent</code> that caused the
3047 * <code>ToolTipManager</code> to show the tooltip
3048 * @return always returns <code>null</code>
3049 */
3050 public Point getToolTipLocation(MouseEvent event) {
3051 return null;
3052 }
3053
3054 /**
3055 * Returns the preferred location to display the popup menu in this
3056 * component's coordinate system. It is up to the look and feel to
3057 * honor this property, some may choose to ignore it.
3058 * If {@code null}, the look and feel will choose a suitable location.
3059 *
3060 * @param event the {@code MouseEvent} that triggered the popup to be
3061 * shown, or {@code null} if the popup is not being shown as the
3062 * result of a mouse event
3063 * @return location to display the {@code JPopupMenu}, or {@code null}
3064 * @since 1.5
3065 */
3066 public Point getPopupLocation(MouseEvent event) {
3067 return null;
3068 }
3069
3070
3071 /**
3072 * Returns the instance of <code>JToolTip</code> that should be used
3073 * to display the tooltip.
3074 * Components typically would not override this method,
3075 * but it can be used to
3076 * cause different tooltips to be displayed differently.
3077 *
3078 * @return the <code>JToolTip</code> used to display this toolTip
3079 */
3080 public JToolTip createToolTip() {
3081 JToolTip tip = new JToolTip();
3082 tip.setComponent(this);
3083 return tip;
3084 }
3085
3086 /**
3087 * Forwards the <code>scrollRectToVisible()</code> message to the
3088 * <code>JComponent</code>'s parent. Components that can service
3089 * the request, such as <code>JViewport</code>,
3090 * override this method and perform the scrolling.
3091 *
3092 * @param aRect the visible <code>Rectangle</code>
3093 * @see JViewport
3094 */
3095 public void scrollRectToVisible(Rectangle aRect) {
3096 Container parent;
3097 int dx = getX(), dy = getY();
3098
3099 for (parent = getParent();
3100 !(parent == null) &&
3101 !(parent instanceof JComponent) &&
3102 !(parent instanceof CellRendererPane);
3103 parent = parent.getParent()) {
3104 Rectangle bounds = parent.getBounds();
3105
3106 dx += bounds.x;
3107 dy += bounds.y;
3108 }
3109
3110 if (!(parent == null) && !(parent instanceof CellRendererPane)) {
3111 aRect.x += dx;
3112 aRect.y += dy;
3113
3114 ((JComponent)parent).scrollRectToVisible(aRect);
3115 aRect.x -= dx;
3116 aRect.y -= dy;
3117 }
3118 }
3119
3120 /**
3121 * Sets the <code>autoscrolls</code> property.
3122 * If <code>true</code> mouse dragged events will be
3123 * synthetically generated when the mouse is dragged
3124 * outside of the component's bounds and mouse motion
3125 * has paused (while the button continues to be held
3126 * down). The synthetic events make it appear that the
3127 * drag gesture has resumed in the direction established when
3128 * the component's boundary was crossed. Components that
3129 * support autoscrolling must handle <code>mouseDragged</code>
3130 * events by calling <code>scrollRectToVisible</code> with a
3131 * rectangle that contains the mouse event's location. All of
3132 * the Swing components that support item selection and are
3133 * typically displayed in a <code>JScrollPane</code>
3134 * (<code>JTable</code>, <code>JList</code>, <code>JTree</code>,
3135 * <code>JTextArea</code>, and <code>JEditorPane</code>)
3136 * already handle mouse dragged events in this way. To enable
3137 * autoscrolling in any other component, add a mouse motion
3138 * listener that calls <code>scrollRectToVisible</code>.
3139 * For example, given a <code>JPanel</code>, <code>myPanel</code>:
3140 * <pre>
3141 * MouseMotionListener doScrollRectToVisible = new MouseMotionAdapter() {
3142 * public void mouseDragged(MouseEvent e) {
3143 * Rectangle r = new Rectangle(e.getX(), e.getY(), 1, 1);
3144 * ((JPanel)e.getSource()).scrollRectToVisible(r);
3145 * }
3146 * };
3147 * myPanel.addMouseMotionListener(doScrollRectToVisible);
3148 * </pre>
3149 * The default value of the <code>autoScrolls</code>
3150 * property is <code>false</code>.
3151 *
3152 * @param autoscrolls if true, synthetic mouse dragged events
3153 * are generated when the mouse is dragged outside of a component's
3154 * bounds and the mouse button continues to be held down; otherwise
3155 * false
3156 * @see #getAutoscrolls
3157 * @see JViewport
3158 * @see JScrollPane
3159 */
3160 @BeanProperty(bound = false, expert = true, description
3161 = "Determines if this component automatically scrolls its contents when dragged.")
3162 public void setAutoscrolls(boolean autoscrolls) {
3163 setFlag(AUTOSCROLLS_SET, true);
3164 if (this.autoscrolls != autoscrolls) {
3165 this.autoscrolls = autoscrolls;
3166 if (autoscrolls) {
3167 enableEvents(AWTEvent.MOUSE_EVENT_MASK);
3168 enableEvents(AWTEvent.MOUSE_MOTION_EVENT_MASK);
3169 }
3170 else {
3171 Autoscroller.stop(this);
3172 }
3173 }
3174 }
3175
3176 /**
3177 * Gets the <code>autoscrolls</code> property.
3178 *
3179 * @return the value of the <code>autoscrolls</code> property
3180 * @see JViewport
3181 * @see #setAutoscrolls
3182 */
3183 public boolean getAutoscrolls() {
3184 return autoscrolls;
3185 }
3186
3187 /**
3188 * Sets the {@code TransferHandler}, which provides support for transfer
3189 * of data into and out of this component via cut/copy/paste and drag
3190 * and drop. This may be {@code null} if the component does not support
3191 * data transfer operations.
3192 * <p>
3193 * If the new {@code TransferHandler} is not {@code null}, this method
3194 * also installs a <b>new</b> {@code DropTarget} on the component to
3195 * activate drop handling through the {@code TransferHandler} and activate
3196 * any built-in support (such as calculating and displaying potential drop
3197 * locations). If you do not wish for this component to respond in any way
3198 * to drops, you can disable drop support entirely either by removing the
3199 * drop target ({@code setDropTarget(null)}) or by de-activating it
3200 * ({@code getDropTaget().setActive(false)}).
3201 * <p>
3202 * If the new {@code TransferHandler} is {@code null}, this method removes
3203 * the drop target.
3204 * <p>
3205 * Under two circumstances, this method does not modify the drop target:
3206 * First, if the existing drop target on this component was explicitly
3207 * set by the developer to a {@code non-null} value. Second, if the
3208 * system property {@code suppressSwingDropSupport} is {@code true}. The
3209 * default value for the system property is {@code false}.
3210 * <p>
3211 * Please see
3212 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/dnd/index.html">
3213 * How to Use Drag and Drop and Data Transfer</a>,
3214 * a section in <em>The Java Tutorial</em>, for more information.
3215 *
3216 * @param newHandler the new {@code TransferHandler}
3217 *
3218 * @see TransferHandler
3219 * @see #getTransferHandler
3220 * @since 1.4
3221 */
3222 @BeanProperty(hidden = true, description
3223 = "Mechanism for transfer of data to and from the component")
3224 public void setTransferHandler(TransferHandler newHandler) {
3225 TransferHandler oldHandler = (TransferHandler)getClientProperty(
3226 JComponent_TRANSFER_HANDLER);
3227 putClientProperty(JComponent_TRANSFER_HANDLER, newHandler);
3228
3229 SwingUtilities.installSwingDropTargetAsNecessary(this, newHandler);
3230 firePropertyChange("transferHandler", oldHandler, newHandler);
3231 }
3232
3233 /**
3234 * Gets the <code>transferHandler</code> property.
3235 *
3236 * @return the value of the <code>transferHandler</code> property
3237 *
3238 * @see TransferHandler
3239 * @see #setTransferHandler
3240 * @since 1.4
3241 */
3242 public TransferHandler getTransferHandler() {
3243 return (TransferHandler)getClientProperty(JComponent_TRANSFER_HANDLER);
3244 }
3245
3246 /**
3247 * Calculates a custom drop location for this type of component,
3248 * representing where a drop at the given point should insert data.
3249 * <code>null</code> is returned if this component doesn't calculate
3250 * custom drop locations. In this case, <code>TransferHandler</code>
3251 * will provide a default <code>DropLocation</code> containing just
3252 * the point.
3253 *
3254 * @param p the point to calculate a drop location for
3255 * @return the drop location, or <code>null</code>
3256 */
3257 TransferHandler.DropLocation dropLocationForPoint(Point p) {
3258 return null;
3259 }
3260
3261 /**
3262 * Called to set or clear the drop location during a DnD operation.
3263 * In some cases, the component may need to use its internal selection
3264 * temporarily to indicate the drop location. To help facilitate this,
3265 * this method returns and accepts as a parameter a state object.
3266 * This state object can be used to store, and later restore, the selection
3267 * state. Whatever this method returns will be passed back to it in
3268 * future calls, as the state parameter. If it wants the DnD system to
3269 * continue storing the same state, it must pass it back every time.
3270 * Here's how this is used:
3271 * <p>
3272 * Let's say that on the first call to this method the component decides
3273 * to save some state (because it is about to use the selection to show
3274 * a drop index). It can return a state object to the caller encapsulating
3275 * any saved selection state. On a second call, let's say the drop location
3276 * is being changed to something else. The component doesn't need to
3277 * restore anything yet, so it simply passes back the same state object
3278 * to have the DnD system continue storing it. Finally, let's say this
3279 * method is messaged with <code>null</code>. This means DnD
3280 * is finished with this component for now, meaning it should restore
3281 * state. At this point, it can use the state parameter to restore
3282 * said state, and of course return <code>null</code> since there's
3283 * no longer anything to store.
3284 *
3285 * @param location the drop location (as calculated by
3286 * <code>dropLocationForPoint</code>) or <code>null</code>
3287 * if there's no longer a valid drop location
3288 * @param state the state object saved earlier for this component,
3289 * or <code>null</code>
3290 * @param forDrop whether or not the method is being called because an
3291 * actual drop occurred
3292 * @return any saved state for this component, or <code>null</code> if none
3293 */
3294 Object setDropLocation(TransferHandler.DropLocation location,
3295 Object state,
3296 boolean forDrop) {
3297
3298 return null;
3299 }
3300
3301 /**
3302 * Called to indicate to this component that DnD is done.
3303 * Needed by <code>JTree</code>.
3304 */
3305 void dndDone() {
3306 }
3307
3308 /**
3309 * Processes mouse events occurring on this component by
3310 * dispatching them to any registered
3311 * <code>MouseListener</code> objects, refer to
3312 * {@link java.awt.Component#processMouseEvent(MouseEvent)}
3313 * for a complete description of this method.
3314 *
3315 * @param e the mouse event
3316 * @see java.awt.Component#processMouseEvent
3317 * @since 1.5
3318 */
3319 protected void processMouseEvent(MouseEvent e) {
3320 if (autoscrolls && e.getID() == MouseEvent.MOUSE_RELEASED) {
3321 Autoscroller.stop(this);
3322 }
3323 super.processMouseEvent(e);
3324 }
3325
3326 /**
3327 * Processes mouse motion events, such as MouseEvent.MOUSE_DRAGGED.
3328 *
3329 * @param e the <code>MouseEvent</code>
3330 * @see MouseEvent
3331 */
3332 protected void processMouseMotionEvent(MouseEvent e) {
3333 boolean dispatch = true;
3334 if (autoscrolls && e.getID() == MouseEvent.MOUSE_DRAGGED) {
3335 // We don't want to do the drags when the mouse moves if we're
3336 // autoscrolling. It makes it feel spastic.
3337 dispatch = !Autoscroller.isRunning(this);
3338 Autoscroller.processMouseDragged(e);
3339 }
3340 if (dispatch) {
3341 super.processMouseMotionEvent(e);
3342 }
3343 }
3344
3345 // Inner classes can't get at this method from a super class
3346 void superProcessMouseMotionEvent(MouseEvent e) {
3347 super.processMouseMotionEvent(e);
3348 }
3349
3350 /**
3351 * This is invoked by the <code>RepaintManager</code> if
3352 * <code>createImage</code> is called on the component.
3353 *
3354 * @param newValue true if the double buffer image was created from this component
3355 */
3356 void setCreatedDoubleBuffer(boolean newValue) {
3357 setFlag(CREATED_DOUBLE_BUFFER, newValue);
3358 }
3359
3360 /**
3361 * Returns true if the <code>RepaintManager</code>
3362 * created the double buffer image from the component.
3363 *
3364 * @return true if this component had a double buffer image, false otherwise
3365 */
3366 boolean getCreatedDoubleBuffer() {
3367 return getFlag(CREATED_DOUBLE_BUFFER);
3368 }
3369
3370 /**
3371 * <code>ActionStandin</code> is used as a standin for
3372 * <code>ActionListeners</code> that are
3373 * added via <code>registerKeyboardAction</code>.
3374 */
3375 final class ActionStandin implements Action {
3376 private final ActionListener actionListener;
3377 private final String command;
3378 // This will be non-null if actionListener is an Action.
3379 private final Action action;
3380
3381 ActionStandin(ActionListener actionListener, String command) {
3382 this.actionListener = actionListener;
3383 if (actionListener instanceof Action) {
3384 this.action = (Action)actionListener;
3385 }
3386 else {
3387 this.action = null;
3388 }
3389 this.command = command;
3390 }
3391
3392 public Object getValue(String key) {
3393 if (key != null) {
3394 if (key.equals(Action.ACTION_COMMAND_KEY)) {
3395 return command;
3396 }
3397 if (action != null) {
3398 return action.getValue(key);
3399 }
3400 if (key.equals(NAME)) {
3401 return "ActionStandin";
3402 }
3403 }
3404 return null;
3405 }
3406
3407 public boolean isEnabled() {
3408 if (actionListener == null) {
3409 // This keeps the old semantics where
3410 // registerKeyboardAction(null) would essentialy remove
3411 // the binding. We don't remove the binding from the
3412 // InputMap as that would still allow parent InputMaps
3413 // bindings to be accessed.
3414 return false;
3415 }
3416 if (action == null) {
3417 return true;
3418 }
3419 return action.isEnabled();
3420 }
3421
3422 public void actionPerformed(ActionEvent ae) {
3423 if (actionListener != null) {
3424 actionListener.actionPerformed(ae);
3425 }
3426 }
3427
3428 // We don't allow any values to be added.
3429 public void putValue(String key, Object value) {}
3430
3431 // Does nothing, our enabledness is determiend from our asociated
3432 // action.
3433 public void setEnabled(boolean b) { }
3434
3435 public void addPropertyChangeListener
3436 (PropertyChangeListener listener) {}
3437 public void removePropertyChangeListener
3438 (PropertyChangeListener listener) {}
3439 }
3440
3441
3442 // This class is used by the KeyboardState class to provide a single
3443 // instance that can be stored in the AppContext.
3444 static final class IntVector {
3445 int array[] = null;
3446 int count = 0;
3447 int capacity = 0;
3448
3449 int size() {
3450 return count;
3451 }
3452
3453 int elementAt(int index) {
3454 return array[index];
3455 }
3456
3457 void addElement(int value) {
3458 if (count == capacity) {
3459 capacity = (capacity + 2) * 2;
3460 int[] newarray = new int[capacity];
3461 if (count > 0) {
3462 System.arraycopy(array, 0, newarray, 0, count);
3463 }
3464 array = newarray;
3465 }
3466 array[count++] = value;
3467 }
3468
3469 void setElementAt(int value, int index) {
3470 array[index] = value;
3471 }
3472 }
3473
3474 @SuppressWarnings("serial")
3475 static class KeyboardState implements Serializable {
3476 private static final Object keyCodesKey =
3477 JComponent.KeyboardState.class;
3478
3479 // Get the array of key codes from the AppContext.
3480 static IntVector getKeyCodeArray() {
3481 IntVector iv =
3482 (IntVector)SwingUtilities.appContextGet(keyCodesKey);
3483 if (iv == null) {
3484 iv = new IntVector();
3485 SwingUtilities.appContextPut(keyCodesKey, iv);
3486 }
3487 return iv;
3488 }
3489
3490 static void registerKeyPressed(int keyCode) {
3491 IntVector kca = getKeyCodeArray();
3492 int count = kca.size();
3493 int i;
3494 for(i=0;i<count;i++) {
3495 if(kca.elementAt(i) == -1){
3496 kca.setElementAt(keyCode, i);
3497 return;
3498 }
3499 }
3500 kca.addElement(keyCode);
3501 }
3502
3503 static void registerKeyReleased(int keyCode) {
3504 IntVector kca = getKeyCodeArray();
3505 int count = kca.size();
3506 int i;
3507 for(i=0;i<count;i++) {
3508 if(kca.elementAt(i) == keyCode) {
3509 kca.setElementAt(-1, i);
3510 return;
3511 }
3512 }
3513 }
3514
3515 static boolean keyIsPressed(int keyCode) {
3516 IntVector kca = getKeyCodeArray();
3517 int count = kca.size();
3518 int i;
3519 for(i=0;i<count;i++) {
3520 if(kca.elementAt(i) == keyCode) {
3521 return true;
3522 }
3523 }
3524 return false;
3525 }
3526
3527 /**
3528 * Updates internal state of the KeyboardState and returns true
3529 * if the event should be processed further.
3530 */
3531 static boolean shouldProcess(KeyEvent e) {
3532 switch (e.getID()) {
3533 case KeyEvent.KEY_PRESSED:
3534 if (!keyIsPressed(e.getKeyCode())) {
3535 registerKeyPressed(e.getKeyCode());
3536 }
3537 return true;
3538 case KeyEvent.KEY_RELEASED:
3539 // We are forced to process VK_PRINTSCREEN separately because
3540 // the Windows doesn't generate the key pressed event for
3541 // printscreen and it block the processing of key release
3542 // event for printscreen.
3543 if (keyIsPressed(e.getKeyCode()) || e.getKeyCode()==KeyEvent.VK_PRINTSCREEN) {
3544 registerKeyReleased(e.getKeyCode());
3545 return true;
3546 }
3547 return false;
3548 case KeyEvent.KEY_TYPED:
3549 return true;
3550 default:
3551 // Not a known KeyEvent type, bail.
3552 return false;
3553 }
3554 }
3555 }
3556
3557 static final sun.awt.RequestFocusController focusController =
3558 new sun.awt.RequestFocusController() {
3559 public boolean acceptRequestFocus(Component from, Component to,
3560 boolean temporary, boolean focusedWindowChangeAllowed,
3561 sun.awt.CausedFocusEvent.Cause cause)
3562 {
3563 if ((to == null) || !(to instanceof JComponent)) {
3564 return true;
3565 }
3566
3567 if ((from == null) || !(from instanceof JComponent)) {
3568 return true;
3569 }
3570
3571 JComponent target = (JComponent) to;
3572 if (!target.getVerifyInputWhenFocusTarget()) {
3573 return true;
3574 }
3575
3576 JComponent jFocusOwner = (JComponent)from;
3577 InputVerifier iv = jFocusOwner.getInputVerifier();
3578
3579 if (iv == null) {
3580 return true;
3581 } else {
3582 Object currentSource = SwingUtilities.appContextGet(
3583 INPUT_VERIFIER_SOURCE_KEY);
3584 if (currentSource == jFocusOwner) {
3585 // We're currently calling into the InputVerifier
3586 // for this component, so allow the focus change.
3587 return true;
3588 }
3589 SwingUtilities.appContextPut(INPUT_VERIFIER_SOURCE_KEY,
3590 jFocusOwner);
3591 try {
3592 return iv.shouldYieldFocus(jFocusOwner);
3593 } finally {
3594 if (currentSource != null) {
3595 // We're already in the InputVerifier for
3596 // currentSource. By resetting the currentSource
3597 // we ensure that if the InputVerifier for
3598 // currentSource does a requestFocus, we don't
3599 // try and run the InputVerifier again.
3600 SwingUtilities.appContextPut(
3601 INPUT_VERIFIER_SOURCE_KEY, currentSource);
3602 } else {
3603 SwingUtilities.appContextRemove(
3604 INPUT_VERIFIER_SOURCE_KEY);
3605 }
3606 }
3607 }
3608 }
3609 };
3610
3611 /*
3612 * --- Accessibility Support ---
3613 */
3614
3615 /**
3616 * @deprecated As of JDK version 1.1,
3617 * replaced by <code>java.awt.Component.setEnabled(boolean)</code>.
3618 */
3619 @Deprecated
3620 public void enable() {
3621 if (isEnabled() != true) {
3622 super.enable();
3623 if (accessibleContext != null) {
3624 accessibleContext.firePropertyChange(
3625 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
3626 null, AccessibleState.ENABLED);
3627 }
3628 }
3629 }
3630
3631 /**
3632 * @deprecated As of JDK version 1.1,
3633 * replaced by <code>java.awt.Component.setEnabled(boolean)</code>.
3634 */
3635 @Deprecated
3636 public void disable() {
3637 if (isEnabled() != false) {
3638 super.disable();
3639 if (accessibleContext != null) {
3640 accessibleContext.firePropertyChange(
3641 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
3642 AccessibleState.ENABLED, null);
3643 }
3644 }
3645 }
3646
3647 /**
3648 * Inner class of JComponent used to provide default support for
3649 * accessibility. This class is not meant to be used directly by
3650 * application developers, but is instead meant only to be
3651 * subclassed by component developers.
3652 * <p>
3653 * <strong>Warning:</strong>
3654 * Serialized objects of this class will not be compatible with
3655 * future Swing releases. The current serialization support is
3656 * appropriate for short term storage or RMI between applications running
3657 * the same version of Swing. As of 1.4, support for long term storage
3658 * of all JavaBeans™
3659 * has been added to the <code>java.beans</code> package.
3660 * Please see {@link java.beans.XMLEncoder}.
3661 */
3662 @SuppressWarnings("serial") // Same-version serialization only
3663 public abstract class AccessibleJComponent extends AccessibleAWTContainer
3664 implements AccessibleExtendedComponent
3665 {
3666 /**
3667 * Though the class is abstract, this should be called by
3668 * all sub-classes.
3669 */
3670 protected AccessibleJComponent() {
3671 super();
3672 }
3673
3674 /**
3675 * Number of PropertyChangeListener objects registered. It's used
3676 * to add/remove ContainerListener and FocusListener to track
3677 * target JComponent's state
3678 */
3679 private transient volatile int propertyListenersCount = 0;
3680
3681 /**
3682 * This field duplicates the function of the accessibleAWTFocusHandler field
3683 * in java.awt.Component.AccessibleAWTComponent, so it has been deprecated.
3684 */
3685 @Deprecated
3686 protected FocusListener accessibleFocusHandler = null;
3687
3688 /**
3689 * Fire PropertyChange listener, if one is registered,
3690 * when children added/removed.
3691 */
3692 protected class AccessibleContainerHandler
3693 implements ContainerListener {
3694 public void componentAdded(ContainerEvent e) {
3695 Component c = e.getChild();
3696 if (c != null && c instanceof Accessible) {
3697 AccessibleJComponent.this.firePropertyChange(
3698 AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,
3699 null, c.getAccessibleContext());
3700 }
3701 }
3702 public void componentRemoved(ContainerEvent e) {
3703 Component c = e.getChild();
3704 if (c != null && c instanceof Accessible) {
3705 AccessibleJComponent.this.firePropertyChange(
3706 AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,
3707 c.getAccessibleContext(), null);
3708 }
3709 }
3710 }
3711
3712 /**
3713 * Fire PropertyChange listener, if one is registered,
3714 * when focus events happen
3715 * @since 1.3
3716 */
3717 protected class AccessibleFocusHandler implements FocusListener {
3718 public void focusGained(FocusEvent event) {
3719 if (accessibleContext != null) {
3720 accessibleContext.firePropertyChange(
3721 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
3722 null, AccessibleState.FOCUSED);
3723 }
3724 }
3725 public void focusLost(FocusEvent event) {
3726 if (accessibleContext != null) {
3727 accessibleContext.firePropertyChange(
3728 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
3729 AccessibleState.FOCUSED, null);
3730 }
3731 }
3732 } // inner class AccessibleFocusHandler
3733
3734
3735 /**
3736 * Adds a PropertyChangeListener to the listener list.
3737 *
3738 * @param listener the PropertyChangeListener to be added
3739 */
3740 public void addPropertyChangeListener(PropertyChangeListener listener) {
3741 super.addPropertyChangeListener(listener);
3742 }
3743
3744 /**
3745 * Removes a PropertyChangeListener from the listener list.
3746 * This removes a PropertyChangeListener that was registered
3747 * for all properties.
3748 *
3749 * @param listener the PropertyChangeListener to be removed
3750 */
3751 public void removePropertyChangeListener(PropertyChangeListener listener) {
3752 super.removePropertyChangeListener(listener);
3753 }
3754
3755
3756
3757 /**
3758 * Recursively search through the border hierarchy (if it exists)
3759 * for a TitledBorder with a non-null title. This does a depth
3760 * first search on first the inside borders then the outside borders.
3761 * The assumption is that titles make really pretty inside borders
3762 * but not very pretty outside borders in compound border situations.
3763 * It's rather arbitrary, but hopefully decent UI programmers will
3764 * not create multiple titled borders for the same component.
3765 *
3766 * @param b the {@code Border} for which to retrieve its title
3767 * @return the border's title as a {@code String}, null if it has
3768 * no title
3769 */
3770 protected String getBorderTitle(Border b) {
3771 String s;
3772 if (b instanceof TitledBorder) {
3773 return ((TitledBorder) b).getTitle();
3774 } else if (b instanceof CompoundBorder) {
3775 s = getBorderTitle(((CompoundBorder) b).getInsideBorder());
3776 if (s == null) {
3777 s = getBorderTitle(((CompoundBorder) b).getOutsideBorder());
3778 }
3779 return s;
3780 } else {
3781 return null;
3782 }
3783 }
3784
3785 // AccessibleContext methods
3786 //
3787 /**
3788 * Gets the accessible name of this object. This should almost never
3789 * return java.awt.Component.getName(), as that generally isn't
3790 * a localized name, and doesn't have meaning for the user. If the
3791 * object is fundamentally a text object (such as a menu item), the
3792 * accessible name should be the text of the object (for example,
3793 * "save").
3794 * If the object has a tooltip, the tooltip text may also be an
3795 * appropriate String to return.
3796 *
3797 * @return the localized name of the object -- can be null if this
3798 * object does not have a name
3799 * @see AccessibleContext#setAccessibleName
3800 */
3801 public String getAccessibleName() {
3802 String name = accessibleName;
3803
3804 // fallback to the client name property
3805 //
3806 if (name == null) {
3807 name = (String)getClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY);
3808 }
3809
3810 // fallback to the titled border if it exists
3811 //
3812 if (name == null) {
3813 name = getBorderTitle(getBorder());
3814 }
3815
3816 // fallback to the label labeling us if it exists
3817 //
3818 if (name == null) {
3819 Object o = getClientProperty(JLabel.LABELED_BY_PROPERTY);
3820 if (o instanceof Accessible) {
3821 AccessibleContext ac = ((Accessible) o).getAccessibleContext();
3822 if (ac != null) {
3823 name = ac.getAccessibleName();
3824 }
3825 }
3826 }
3827 return name;
3828 }
3829
3830 /**
3831 * Gets the accessible description of this object. This should be
3832 * a concise, localized description of what this object is - what
3833 * is its meaning to the user. If the object has a tooltip, the
3834 * tooltip text may be an appropriate string to return, assuming
3835 * it contains a concise description of the object (instead of just
3836 * the name of the object - for example a "Save" icon on a toolbar that
3837 * had "save" as the tooltip text shouldn't return the tooltip
3838 * text as the description, but something like "Saves the current
3839 * text document" instead).
3840 *
3841 * @return the localized description of the object -- can be null if
3842 * this object does not have a description
3843 * @see AccessibleContext#setAccessibleDescription
3844 */
3845 public String getAccessibleDescription() {
3846 String description = accessibleDescription;
3847
3848 // fallback to the client description property
3849 //
3850 if (description == null) {
3851 description = (String)getClientProperty(AccessibleContext.ACCESSIBLE_DESCRIPTION_PROPERTY);
3852 }
3853
3854 // fallback to the tool tip text if it exists
3855 //
3856 if (description == null) {
3857 try {
3858 description = getToolTipText();
3859 } catch (Exception e) {
3860 // Just in case the subclass overrode the
3861 // getToolTipText method and actually
3862 // requires a MouseEvent.
3863 // [[[FIXME: WDW - we probably should require this
3864 // method to take a MouseEvent and just pass it on
3865 // to getToolTipText. The swing-feedback traffic
3866 // leads me to believe getToolTipText might change,
3867 // though, so I was hesitant to make this change at
3868 // this time.]]]
3869 }
3870 }
3871
3872 // fallback to the label labeling us if it exists
3873 //
3874 if (description == null) {
3875 Object o = getClientProperty(JLabel.LABELED_BY_PROPERTY);
3876 if (o instanceof Accessible) {
3877 AccessibleContext ac = ((Accessible) o).getAccessibleContext();
3878 if (ac != null) {
3879 description = ac.getAccessibleDescription();
3880 }
3881 }
3882 }
3883
3884 return description;
3885 }
3886
3887 /**
3888 * Gets the role of this object.
3889 *
3890 * @return an instance of AccessibleRole describing the role of the
3891 * object
3892 * @see AccessibleRole
3893 */
3894 public AccessibleRole getAccessibleRole() {
3895 return AccessibleRole.SWING_COMPONENT;
3896 }
3897
3898 /**
3899 * Gets the state of this object.
3900 *
3901 * @return an instance of AccessibleStateSet containing the current
3902 * state set of the object
3903 * @see AccessibleState
3904 */
3905 public AccessibleStateSet getAccessibleStateSet() {
3906 AccessibleStateSet states = super.getAccessibleStateSet();
3907 if (JComponent.this.isOpaque()) {
3908 states.add(AccessibleState.OPAQUE);
3909 }
3910 return states;
3911 }
3912
3913 /**
3914 * Returns the number of accessible children in the object. If all
3915 * of the children of this object implement Accessible, than this
3916 * method should return the number of children of this object.
3917 *
3918 * @return the number of accessible children in the object.
3919 */
3920 public int getAccessibleChildrenCount() {
3921 return super.getAccessibleChildrenCount();
3922 }
3923
3924 /**
3925 * Returns the nth Accessible child of the object.
3926 *
3927 * @param i zero-based index of child
3928 * @return the nth Accessible child of the object
3929 */
3930 public Accessible getAccessibleChild(int i) {
3931 return super.getAccessibleChild(i);
3932 }
3933
3934 // ----- AccessibleExtendedComponent
3935
3936 /**
3937 * Returns the AccessibleExtendedComponent
3938 *
3939 * @return the AccessibleExtendedComponent
3940 */
3941 AccessibleExtendedComponent getAccessibleExtendedComponent() {
3942 return this;
3943 }
3944
3945 /**
3946 * Returns the tool tip text
3947 *
3948 * @return the tool tip text, if supported, of the object;
3949 * otherwise, null
3950 * @since 1.4
3951 */
3952 public String getToolTipText() {
3953 return JComponent.this.getToolTipText();
3954 }
3955
3956 /**
3957 * Returns the titled border text
3958 *
3959 * @return the titled border text, if supported, of the object;
3960 * otherwise, null
3961 * @since 1.4
3962 */
3963 public String getTitledBorderText() {
3964 Border border = JComponent.this.getBorder();
3965 if (border instanceof TitledBorder) {
3966 return ((TitledBorder)border).getTitle();
3967 } else {
3968 return null;
3969 }
3970 }
3971
3972 /**
3973 * Returns key bindings associated with this object
3974 *
3975 * @return the key bindings, if supported, of the object;
3976 * otherwise, null
3977 * @see AccessibleKeyBinding
3978 * @since 1.4
3979 */
3980 public AccessibleKeyBinding getAccessibleKeyBinding(){
3981 // Try to get the linked label's mnemonic if it exists
3982 Object o = getClientProperty(JLabel.LABELED_BY_PROPERTY);
3983 if (o instanceof Accessible){
3984 AccessibleContext ac = ((Accessible) o).getAccessibleContext();
3985 if (ac != null){
3986 AccessibleComponent comp = ac.getAccessibleComponent();
3987 if (! (comp instanceof AccessibleExtendedComponent))
3988 return null;
3989 return ((AccessibleExtendedComponent)comp).getAccessibleKeyBinding();
3990 }
3991 }
3992 return null;
3993 }
3994 } // inner class AccessibleJComponent
3995
3996
3997 /**
3998 * Returns an <code>ArrayTable</code> used for
3999 * key/value "client properties" for this component. If the
4000 * <code>clientProperties</code> table doesn't exist, an empty one
4001 * will be created.
4002 *
4003 * @return an ArrayTable
4004 * @see #putClientProperty
4005 * @see #getClientProperty
4006 */
4007 private ArrayTable getClientProperties() {
4008 if (clientProperties == null) {
4009 clientProperties = new ArrayTable();
4010 }
4011 return clientProperties;
4012 }
4013
4014
4015 /**
4016 * Returns the value of the property with the specified key. Only
4017 * properties added with <code>putClientProperty</code> will return
4018 * a non-<code>null</code> value.
4019 *
4020 * @param key the being queried
4021 * @return the value of this property or <code>null</code>
4022 * @see #putClientProperty
4023 */
4024 public final Object getClientProperty(Object key) {
4025 if (key == RenderingHints.KEY_TEXT_ANTIALIASING) {
4026 return aaHint;
4027 } else if (key == RenderingHints.KEY_TEXT_LCD_CONTRAST) {
4028 return lcdRenderingHint;
4029 }
4030 if(clientProperties == null) {
4031 return null;
4032 } else {
4033 synchronized(clientProperties) {
4034 return clientProperties.get(key);
4035 }
4036 }
4037 }
4038
4039 /**
4040 * Adds an arbitrary key/value "client property" to this component.
4041 * <p>
4042 * The <code>get/putClientProperty</code> methods provide access to
4043 * a small per-instance hashtable. Callers can use get/putClientProperty
4044 * to annotate components that were created by another module.
4045 * For example, a
4046 * layout manager might store per child constraints this way. For example:
4047 * <pre>
4048 * componentA.putClientProperty("to the left of", componentB);
4049 * </pre>
4050 * If value is <code>null</code> this method will remove the property.
4051 * Changes to client properties are reported with
4052 * <code>PropertyChange</code> events.
4053 * The name of the property (for the sake of PropertyChange
4054 * events) is <code>key.toString()</code>.
4055 * <p>
4056 * The <code>clientProperty</code> dictionary is not intended to
4057 * support large
4058 * scale extensions to JComponent nor should be it considered an
4059 * alternative to subclassing when designing a new component.
4060 *
4061 * @param key the new client property key
4062 * @param value the new client property value; if <code>null</code>
4063 * this method will remove the property
4064 * @see #getClientProperty
4065 * @see #addPropertyChangeListener
4066 */
4067 public final void putClientProperty(Object key, Object value) {
4068 if (key == RenderingHints.KEY_TEXT_ANTIALIASING) {
4069 aaHint = value;
4070 return;
4071 } else if (key == RenderingHints.KEY_TEXT_LCD_CONTRAST) {
4072 lcdRenderingHint = value;
4073 return;
4074 }
4075 if (value == null && clientProperties == null) {
4076 // Both the value and ArrayTable are null, implying we don't
4077 // have to do anything.
4078 return;
4079 }
4080 ArrayTable clientProperties = getClientProperties();
4081 Object oldValue;
4082 synchronized(clientProperties) {
4083 oldValue = clientProperties.get(key);
4084 if (value != null) {
4085 clientProperties.put(key, value);
4086 } else if (oldValue != null) {
4087 clientProperties.remove(key);
4088 } else {
4089 // old == new == null
4090 return;
4091 }
4092 }
4093 clientPropertyChanged(key, oldValue, value);
4094 firePropertyChange(key.toString(), oldValue, value);
4095 }
4096
4097 // Invoked from putClientProperty. This is provided for subclasses
4098 // in Swing.
4099 void clientPropertyChanged(Object key, Object oldValue,
4100 Object newValue) {
4101 }
4102
4103
4104 /*
4105 * Sets the property with the specified name to the specified value if
4106 * the property has not already been set by the client program.
4107 * This method is used primarily to set UI defaults for properties
4108 * with primitive types, where the values cannot be marked with
4109 * UIResource.
4110 * @see LookAndFeel#installProperty
4111 * @param propertyName String containing the name of the property
4112 * @param value Object containing the property value
4113 */
4114 void setUIProperty(String propertyName, Object value) {
4115 if (propertyName == "opaque") {
4116 if (!getFlag(OPAQUE_SET)) {
4117 setOpaque(((Boolean)value).booleanValue());
4118 setFlag(OPAQUE_SET, false);
4119 }
4120 } else if (propertyName == "autoscrolls") {
4121 if (!getFlag(AUTOSCROLLS_SET)) {
4122 setAutoscrolls(((Boolean)value).booleanValue());
4123 setFlag(AUTOSCROLLS_SET, false);
4124 }
4125 } else if (propertyName == "focusTraversalKeysForward") {
4126 @SuppressWarnings("unchecked")
4127 Set<AWTKeyStroke> strokeSet = (Set<AWTKeyStroke>) value;
4128 if (!getFlag(FOCUS_TRAVERSAL_KEYS_FORWARD_SET)) {
4129 super.setFocusTraversalKeys(KeyboardFocusManager.
4130 FORWARD_TRAVERSAL_KEYS,
4131 strokeSet);
4132 }
4133 } else if (propertyName == "focusTraversalKeysBackward") {
4134 @SuppressWarnings("unchecked")
4135 Set<AWTKeyStroke> strokeSet = (Set<AWTKeyStroke>) value;
4136 if (!getFlag(FOCUS_TRAVERSAL_KEYS_BACKWARD_SET)) {
4137 super.setFocusTraversalKeys(KeyboardFocusManager.
4138 BACKWARD_TRAVERSAL_KEYS,
4139 strokeSet);
4140 }
4141 } else {
4142 throw new IllegalArgumentException("property \""+
4143 propertyName+ "\" cannot be set using this method");
4144 }
4145 }
4146
4147
4148 /**
4149 * Sets the focus traversal keys for a given traversal operation for this
4150 * Component.
4151 * Refer to
4152 * {@link java.awt.Component#setFocusTraversalKeys}
4153 * for a complete description of this method.
4154 * <p>
4155 * This method may throw a {@code ClassCastException} if any {@code Object}
4156 * in {@code keystrokes} is not an {@code AWTKeyStroke}.
4157 *
4158 * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
4159 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, or
4160 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS
4161 * @param keystrokes the Set of AWTKeyStroke for the specified operation
4162 * @see java.awt.KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS
4163 * @see java.awt.KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS
4164 * @see java.awt.KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
4165 * @throws IllegalArgumentException if id is not one of
4166 * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
4167 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, or
4168 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or if keystrokes
4169 * contains null, or if any keystroke represents a KEY_TYPED event,
4170 * or if any keystroke already maps to another focus traversal
4171 * operation for this Component
4172 * @since 1.5
4173 */
4174 public void
4175 setFocusTraversalKeys(int id, Set<? extends AWTKeyStroke> keystrokes)
4176 {
4177 if (id == KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS) {
4178 setFlag(FOCUS_TRAVERSAL_KEYS_FORWARD_SET,true);
4179 } else if (id == KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS) {
4180 setFlag(FOCUS_TRAVERSAL_KEYS_BACKWARD_SET,true);
4181 }
4182 super.setFocusTraversalKeys(id,keystrokes);
4183 }
4184
4185 /* --- Transitional java.awt.Component Support ---
4186 * The methods and fields in this section will migrate to
4187 * java.awt.Component in the next JDK release.
4188 */
4189
4190 /**
4191 * Returns true if this component is lightweight, that is, if it doesn't
4192 * have a native window system peer.
4193 *
4194 * @param c the {@code Component} to be checked
4195 * @return true if this component is lightweight
4196 */
4197 public static boolean isLightweightComponent(Component c) {
4198 // TODO we cannot call c.isLightweight() because it is incorrectly
4199 // overriden in DelegateContainer on osx.
4200 return AWTAccessor.getComponentAccessor().isLightweight(c);
4201 }
4202
4203
4204 /**
4205 * @deprecated As of JDK 5,
4206 * replaced by <code>Component.setBounds(int, int, int, int)</code>.
4207 * <p>
4208 * Moves and resizes this component.
4209 *
4210 * @param x the new horizontal location
4211 * @param y the new vertical location
4212 * @param w the new width
4213 * @param h the new height
4214 * @see java.awt.Component#setBounds
4215 */
4216 @Deprecated
4217 public void reshape(int x, int y, int w, int h) {
4218 super.reshape(x, y, w, h);
4219 }
4220
4221
4222 /**
4223 * Stores the bounds of this component into "return value"
4224 * <code>rv</code> and returns <code>rv</code>.
4225 * If <code>rv</code> is <code>null</code> a new <code>Rectangle</code>
4226 * is allocated. This version of <code>getBounds</code> is useful
4227 * if the caller wants to avoid allocating a new <code>Rectangle</code>
4228 * object on the heap.
4229 *
4230 * @param rv the return value, modified to the component's bounds
4231 * @return <code>rv</code>; if <code>rv</code> is <code>null</code>
4232 * return a newly created <code>Rectangle</code> with this
4233 * component's bounds
4234 */
4235 public Rectangle getBounds(Rectangle rv) {
4236 if (rv == null) {
4237 return new Rectangle(getX(), getY(), getWidth(), getHeight());
4238 }
4239 else {
4240 rv.setBounds(getX(), getY(), getWidth(), getHeight());
4241 return rv;
4242 }
4243 }
4244
4245
4246 /**
4247 * Stores the width/height of this component into "return value"
4248 * <code>rv</code> and returns <code>rv</code>.
4249 * If <code>rv</code> is <code>null</code> a new <code>Dimension</code>
4250 * object is allocated. This version of <code>getSize</code>
4251 * is useful if the caller wants to avoid allocating a new
4252 * <code>Dimension</code> object on the heap.
4253 *
4254 * @param rv the return value, modified to the component's size
4255 * @return <code>rv</code>
4256 */
4257 public Dimension getSize(Dimension rv) {
4258 if (rv == null) {
4259 return new Dimension(getWidth(), getHeight());
4260 }
4261 else {
4262 rv.setSize(getWidth(), getHeight());
4263 return rv;
4264 }
4265 }
4266
4267
4268 /**
4269 * Stores the x,y origin of this component into "return value"
4270 * <code>rv</code> and returns <code>rv</code>.
4271 * If <code>rv</code> is <code>null</code> a new <code>Point</code>
4272 * is allocated. This version of <code>getLocation</code> is useful
4273 * if the caller wants to avoid allocating a new <code>Point</code>
4274 * object on the heap.
4275 *
4276 * @param rv the return value, modified to the component's location
4277 * @return <code>rv</code>
4278 */
4279 public Point getLocation(Point rv) {
4280 if (rv == null) {
4281 return new Point(getX(), getY());
4282 }
4283 else {
4284 rv.setLocation(getX(), getY());
4285 return rv;
4286 }
4287 }
4288
4289
4290 /**
4291 * Returns the current x coordinate of the component's origin.
4292 * This method is preferable to writing
4293 * <code>component.getBounds().x</code>, or
4294 * <code>component.getLocation().x</code> because it doesn't cause any
4295 * heap allocations.
4296 *
4297 * @return the current x coordinate of the component's origin
4298 */
4299 @BeanProperty(bound = false)
4300 public int getX() { return super.getX(); }
4301
4302
4303 /**
4304 * Returns the current y coordinate of the component's origin.
4305 * This method is preferable to writing
4306 * <code>component.getBounds().y</code>, or
4307 * <code>component.getLocation().y</code> because it doesn't cause any
4308 * heap allocations.
4309 *
4310 * @return the current y coordinate of the component's origin
4311 */
4312 @BeanProperty(bound = false)
4313 public int getY() { return super.getY(); }
4314
4315
4316 /**
4317 * Returns the current width of this component.
4318 * This method is preferable to writing
4319 * <code>component.getBounds().width</code>, or
4320 * <code>component.getSize().width</code> because it doesn't cause any
4321 * heap allocations.
4322 *
4323 * @return the current width of this component
4324 */
4325 @BeanProperty(bound = false)
4326 public int getWidth() { return super.getWidth(); }
4327
4328
4329 /**
4330 * Returns the current height of this component.
4331 * This method is preferable to writing
4332 * <code>component.getBounds().height</code>, or
4333 * <code>component.getSize().height</code> because it doesn't cause any
4334 * heap allocations.
4335 *
4336 * @return the current height of this component
4337 */
4338 @BeanProperty(bound = false)
4339 public int getHeight() { return super.getHeight(); }
4340
4341 /**
4342 * Returns true if this component is completely opaque.
4343 * <p>
4344 * An opaque component paints every pixel within its
4345 * rectangular bounds. A non-opaque component paints only a subset of
4346 * its pixels or none at all, allowing the pixels underneath it to
4347 * "show through". Therefore, a component that does not fully paint
4348 * its pixels provides a degree of transparency.
4349 * <p>
4350 * Subclasses that guarantee to always completely paint their contents
4351 * should override this method and return true.
4352 *
4353 * @return true if this component is completely opaque
4354 * @see #setOpaque
4355 */
4356 public boolean isOpaque() {
4357 return getFlag(IS_OPAQUE);
4358 }
4359
4360 /**
4361 * If true the component paints every pixel within its bounds.
4362 * Otherwise, the component may not paint some or all of its
4363 * pixels, allowing the underlying pixels to show through.
4364 * <p>
4365 * The default value of this property is false for <code>JComponent</code>.
4366 * However, the default value for this property on most standard
4367 * <code>JComponent</code> subclasses (such as <code>JButton</code> and
4368 * <code>JTree</code>) is look-and-feel dependent.
4369 *
4370 * @param isOpaque true if this component should be opaque
4371 * @see #isOpaque
4372 */
4373 @BeanProperty(expert = true, description
4374 = "The component's opacity")
4375 public void setOpaque(boolean isOpaque) {
4376 boolean oldValue = getFlag(IS_OPAQUE);
4377 setFlag(IS_OPAQUE, isOpaque);
4378 setFlag(OPAQUE_SET, true);
4379 firePropertyChange("opaque", oldValue, isOpaque);
4380 }
4381
4382
4383 /**
4384 * If the specified rectangle is completely obscured by any of this
4385 * component's opaque children then returns true. Only direct children
4386 * are considered, more distant descendants are ignored. A
4387 * <code>JComponent</code> is opaque if
4388 * <code>JComponent.isOpaque()</code> returns true, other lightweight
4389 * components are always considered transparent, and heavyweight components
4390 * are always considered opaque.
4391 *
4392 * @param x x value of specified rectangle
4393 * @param y y value of specified rectangle
4394 * @param width width of specified rectangle
4395 * @param height height of specified rectangle
4396 * @return true if the specified rectangle is obscured by an opaque child
4397 */
4398 boolean rectangleIsObscured(int x,int y,int width,int height)
4399 {
4400 int numChildren = getComponentCount();
4401
4402 for(int i = 0; i < numChildren; i++) {
4403 Component child = getComponent(i);
4404 int cx, cy, cw, ch;
4405
4406 cx = child.getX();
4407 cy = child.getY();
4408 cw = child.getWidth();
4409 ch = child.getHeight();
4410
4411 if (x >= cx && (x + width) <= (cx + cw) &&
4412 y >= cy && (y + height) <= (cy + ch) && child.isVisible()) {
4413
4414 if(child instanceof JComponent) {
4415 // System.out.println("A) checking opaque: " + ((JComponent)child).isOpaque() + " " + child);
4416 // System.out.print("B) ");
4417 // Thread.dumpStack();
4418 return child.isOpaque();
4419 } else {
4420 /** Sometimes a heavy weight can have a bound larger than its peer size
4421 * so we should always draw under heavy weights
4422 */
4423 return false;
4424 }
4425 }
4426 }
4427
4428 return false;
4429 }
4430
4431
4432 /**
4433 * Returns the <code>Component</code>'s "visible rect rectangle" - the
4434 * intersection of the visible rectangles for the component <code>c</code>
4435 * and all of its ancestors. The return value is stored in
4436 * <code>visibleRect</code>.
4437 *
4438 * @param c the component
4439 * @param visibleRect a <code>Rectangle</code> computed as the
4440 * intersection of all visible rectangles for the component
4441 * <code>c</code> and all of its ancestors -- this is the
4442 * return value for this method
4443 * @see #getVisibleRect
4444 */
4445 static final void computeVisibleRect(Component c, Rectangle visibleRect) {
4446 Container p = c.getParent();
4447 Rectangle bounds = c.getBounds();
4448
4449 if (p == null || p instanceof Window || p instanceof Applet) {
4450 visibleRect.setBounds(0, 0, bounds.width, bounds.height);
4451 } else {
4452 computeVisibleRect(p, visibleRect);
4453 visibleRect.x -= bounds.x;
4454 visibleRect.y -= bounds.y;
4455 SwingUtilities.computeIntersection(0,0,bounds.width,bounds.height,visibleRect);
4456 }
4457 }
4458
4459
4460 /**
4461 * Returns the <code>Component</code>'s "visible rect rectangle" - the
4462 * intersection of the visible rectangles for this component
4463 * and all of its ancestors. The return value is stored in
4464 * <code>visibleRect</code>.
4465 *
4466 * @param visibleRect a <code>Rectangle</code> computed as the
4467 * intersection of all visible rectangles for this
4468 * component and all of its ancestors -- this is the return
4469 * value for this method
4470 * @see #getVisibleRect
4471 */
4472 public void computeVisibleRect(Rectangle visibleRect) {
4473 computeVisibleRect(this, visibleRect);
4474 }
4475
4476
4477 /**
4478 * Returns the <code>Component</code>'s "visible rectangle" - the
4479 * intersection of this component's visible rectangle,
4480 * <code>new Rectangle(0, 0, getWidth(), getHeight())</code>,
4481 * and all of its ancestors' visible rectangles.
4482 *
4483 * @return the visible rectangle
4484 */
4485 @BeanProperty(bound = false)
4486 public Rectangle getVisibleRect() {
4487 Rectangle visibleRect = new Rectangle();
4488
4489 computeVisibleRect(visibleRect);
4490 return visibleRect;
4491 }
4492
4493 /**
4494 * Support for reporting bound property changes for boolean properties.
4495 * This method can be called when a bound property has changed and it will
4496 * send the appropriate PropertyChangeEvent to any registered
4497 * PropertyChangeListeners.
4498 *
4499 * @param propertyName the property whose value has changed
4500 * @param oldValue the property's previous value
4501 * @param newValue the property's new value
4502 */
4503 public void firePropertyChange(String propertyName,
4504 boolean oldValue, boolean newValue) {
4505 super.firePropertyChange(propertyName, oldValue, newValue);
4506 }
4507
4508
4509 /**
4510 * Support for reporting bound property changes for integer properties.
4511 * This method can be called when a bound property has changed and it will
4512 * send the appropriate PropertyChangeEvent to any registered
4513 * PropertyChangeListeners.
4514 *
4515 * @param propertyName the property whose value has changed
4516 * @param oldValue the property's previous value
4517 * @param newValue the property's new value
4518 */
4519 public void firePropertyChange(String propertyName,
4520 int oldValue, int newValue) {
4521 super.firePropertyChange(propertyName, oldValue, newValue);
4522 }
4523
4524 // XXX This method is implemented as a workaround to a JLS issue with ambiguous
4525 // methods. This should be removed once 4758654 is resolved.
4526 public void firePropertyChange(String propertyName, char oldValue, char newValue) {
4527 super.firePropertyChange(propertyName, oldValue, newValue);
4528 }
4529
4530 /**
4531 * Supports reporting constrained property changes.
4532 * This method can be called when a constrained property has changed
4533 * and it will send the appropriate <code>PropertyChangeEvent</code>
4534 * to any registered <code>VetoableChangeListeners</code>.
4535 *
4536 * @param propertyName the name of the property that was listened on
4537 * @param oldValue the old value of the property
4538 * @param newValue the new value of the property
4539 * @exception java.beans.PropertyVetoException when the attempt to set the
4540 * property is vetoed by the component
4541 */
4542 protected void fireVetoableChange(String propertyName, Object oldValue, Object newValue)
4543 throws java.beans.PropertyVetoException
4544 {
4545 if (vetoableChangeSupport == null) {
4546 return;
4547 }
4548 vetoableChangeSupport.fireVetoableChange(propertyName, oldValue, newValue);
4549 }
4550
4551
4552 /**
4553 * Adds a <code>VetoableChangeListener</code> to the listener list.
4554 * The listener is registered for all properties.
4555 *
4556 * @param listener the <code>VetoableChangeListener</code> to be added
4557 */
4558 public synchronized void addVetoableChangeListener(VetoableChangeListener listener) {
4559 if (vetoableChangeSupport == null) {
4560 vetoableChangeSupport = new java.beans.VetoableChangeSupport(this);
4561 }
4562 vetoableChangeSupport.addVetoableChangeListener(listener);
4563 }
4564
4565
4566 /**
4567 * Removes a <code>VetoableChangeListener</code> from the listener list.
4568 * This removes a <code>VetoableChangeListener</code> that was registered
4569 * for all properties.
4570 *
4571 * @param listener the <code>VetoableChangeListener</code> to be removed
4572 */
4573 public synchronized void removeVetoableChangeListener(VetoableChangeListener listener) {
4574 if (vetoableChangeSupport == null) {
4575 return;
4576 }
4577 vetoableChangeSupport.removeVetoableChangeListener(listener);
4578 }
4579
4580
4581 /**
4582 * Returns an array of all the vetoable change listeners
4583 * registered on this component.
4584 *
4585 * @return all of the component's <code>VetoableChangeListener</code>s
4586 * or an empty
4587 * array if no vetoable change listeners are currently registered
4588 *
4589 * @see #addVetoableChangeListener
4590 * @see #removeVetoableChangeListener
4591 *
4592 * @since 1.4
4593 */
4594 @BeanProperty(bound = false)
4595 public synchronized VetoableChangeListener[] getVetoableChangeListeners() {
4596 if (vetoableChangeSupport == null) {
4597 return new VetoableChangeListener[0];
4598 }
4599 return vetoableChangeSupport.getVetoableChangeListeners();
4600 }
4601
4602
4603 /**
4604 * Returns the top-level ancestor of this component (either the
4605 * containing <code>Window</code> or <code>Applet</code>),
4606 * or <code>null</code> if this component has not
4607 * been added to any container.
4608 *
4609 * @return the top-level <code>Container</code> that this component is in,
4610 * or <code>null</code> if not in any container
4611 */
4612 @BeanProperty(bound = false)
4613 public Container getTopLevelAncestor() {
4614 for(Container p = this; p != null; p = p.getParent()) {
4615 if(p instanceof Window || p instanceof Applet) {
4616 return p;
4617 }
4618 }
4619 return null;
4620 }
4621
4622 private AncestorNotifier getAncestorNotifier() {
4623 return (AncestorNotifier)
4624 getClientProperty(JComponent_ANCESTOR_NOTIFIER);
4625 }
4626
4627 /**
4628 * Registers <code>listener</code> so that it will receive
4629 * <code>AncestorEvents</code> when it or any of its ancestors
4630 * move or are made visible or invisible.
4631 * Events are also sent when the component or its ancestors are added
4632 * or removed from the containment hierarchy.
4633 *
4634 * @param listener the <code>AncestorListener</code> to register
4635 * @see AncestorEvent
4636 */
4637 public void addAncestorListener(AncestorListener listener) {
4638 AncestorNotifier ancestorNotifier = getAncestorNotifier();
4639 if (ancestorNotifier == null) {
4640 ancestorNotifier = new AncestorNotifier(this);
4641 putClientProperty(JComponent_ANCESTOR_NOTIFIER,
4642 ancestorNotifier);
4643 }
4644 ancestorNotifier.addAncestorListener(listener);
4645 }
4646
4647 /**
4648 * Unregisters <code>listener</code> so that it will no longer receive
4649 * <code>AncestorEvents</code>.
4650 *
4651 * @param listener the <code>AncestorListener</code> to be removed
4652 * @see #addAncestorListener
4653 */
4654 public void removeAncestorListener(AncestorListener listener) {
4655 AncestorNotifier ancestorNotifier = getAncestorNotifier();
4656 if (ancestorNotifier == null) {
4657 return;
4658 }
4659 ancestorNotifier.removeAncestorListener(listener);
4660 if (ancestorNotifier.listenerList.getListenerList().length == 0) {
4661 ancestorNotifier.removeAllListeners();
4662 putClientProperty(JComponent_ANCESTOR_NOTIFIER, null);
4663 }
4664 }
4665
4666 /**
4667 * Returns an array of all the ancestor listeners
4668 * registered on this component.
4669 *
4670 * @return all of the component's <code>AncestorListener</code>s
4671 * or an empty
4672 * array if no ancestor listeners are currently registered
4673 *
4674 * @see #addAncestorListener
4675 * @see #removeAncestorListener
4676 *
4677 * @since 1.4
4678 */
4679 @BeanProperty(bound = false)
4680 public AncestorListener[] getAncestorListeners() {
4681 AncestorNotifier ancestorNotifier = getAncestorNotifier();
4682 if (ancestorNotifier == null) {
4683 return new AncestorListener[0];
4684 }
4685 return ancestorNotifier.getAncestorListeners();
4686 }
4687
4688 /**
4689 * Returns an array of all the objects currently registered
4690 * as <code><em>Foo</em>Listener</code>s
4691 * upon this <code>JComponent</code>.
4692 * <code><em>Foo</em>Listener</code>s are registered using the
4693 * <code>add<em>Foo</em>Listener</code> method.
4694 *
4695 * <p>
4696 *
4697 * You can specify the <code>listenerType</code> argument
4698 * with a class literal,
4699 * such as
4700 * <code><em>Foo</em>Listener.class</code>.
4701 * For example, you can query a
4702 * <code>JComponent</code> <code>c</code>
4703 * for its mouse listeners with the following code:
4704 * <pre>MouseListener[] mls = (MouseListener[])(c.getListeners(MouseListener.class));</pre>
4705 * If no such listeners exist, this method returns an empty array.
4706 *
4707 * @param listenerType the type of listeners requested; this parameter
4708 * should specify an interface that descends from
4709 * <code>java.util.EventListener</code>
4710 * @return an array of all objects registered as
4711 * <code><em>Foo</em>Listener</code>s on this component,
4712 * or an empty array if no such
4713 * listeners have been added
4714 * @exception ClassCastException if <code>listenerType</code>
4715 * doesn't specify a class or interface that implements
4716 * <code>java.util.EventListener</code>
4717 *
4718 * @since 1.3
4719 *
4720 * @see #getVetoableChangeListeners
4721 * @see #getAncestorListeners
4722 */
4723 @SuppressWarnings("unchecked") // Casts to (T[])
4724 public <T extends EventListener> T[] getListeners(Class<T> listenerType) {
4725 T[] result;
4726 if (listenerType == AncestorListener.class) {
4727 // AncestorListeners are handled by the AncestorNotifier
4728 result = (T[])getAncestorListeners();
4729 }
4730 else if (listenerType == VetoableChangeListener.class) {
4731 // VetoableChangeListeners are handled by VetoableChangeSupport
4732 result = (T[])getVetoableChangeListeners();
4733 }
4734 else if (listenerType == PropertyChangeListener.class) {
4735 // PropertyChangeListeners are handled by PropertyChangeSupport
4736 result = (T[])getPropertyChangeListeners();
4737 }
4738 else {
4739 result = listenerList.getListeners(listenerType);
4740 }
4741
4742 if (result.length == 0) {
4743 return super.getListeners(listenerType);
4744 }
4745 return result;
4746 }
4747
4748 /**
4749 * Notifies this component that it now has a parent component.
4750 * When this method is invoked, the chain of parent components is
4751 * set up with <code>KeyboardAction</code> event listeners.
4752 * This method is called by the toolkit internally and should
4753 * not be called directly by programs.
4754 *
4755 * @see #registerKeyboardAction
4756 */
4757 public void addNotify() {
4758 super.addNotify();
4759 firePropertyChange("ancestor", null, getParent());
4760
4761 registerWithKeyboardManager(false);
4762 registerNextFocusableComponent();
4763 }
4764
4765
4766 /**
4767 * Notifies this component that it no longer has a parent component.
4768 * When this method is invoked, any <code>KeyboardAction</code>s
4769 * set up in the chain of parent components are removed.
4770 * This method is called by the toolkit internally and should
4771 * not be called directly by programs.
4772 *
4773 * @see #registerKeyboardAction
4774 */
4775 public void removeNotify() {
4776 super.removeNotify();
4777 // This isn't strictly correct. The event shouldn't be
4778 // fired until *after* the parent is set to null. But
4779 // we only get notified before that happens
4780 firePropertyChange("ancestor", getParent(), null);
4781
4782 unregisterWithKeyboardManager();
4783 deregisterNextFocusableComponent();
4784
4785 if (getCreatedDoubleBuffer()) {
4786 RepaintManager.currentManager(this).resetDoubleBuffer();
4787 setCreatedDoubleBuffer(false);
4788 }
4789 if (autoscrolls) {
4790 Autoscroller.stop(this);
4791 }
4792 }
4793
4794
4795 /**
4796 * Adds the specified region to the dirty region list if the component
4797 * is showing. The component will be repainted after all of the
4798 * currently pending events have been dispatched.
4799 *
4800 * @param tm this parameter is not used
4801 * @param x the x value of the dirty region
4802 * @param y the y value of the dirty region
4803 * @param width the width of the dirty region
4804 * @param height the height of the dirty region
4805 * @see #isPaintingOrigin()
4806 * @see java.awt.Component#isShowing
4807 * @see RepaintManager#addDirtyRegion
4808 */
4809 public void repaint(long tm, int x, int y, int width, int height) {
4810 RepaintManager.currentManager(SunToolkit.targetToAppContext(this))
4811 .addDirtyRegion(this, x, y, width, height);
4812 }
4813
4814
4815 /**
4816 * Adds the specified region to the dirty region list if the component
4817 * is showing. The component will be repainted after all of the
4818 * currently pending events have been dispatched.
4819 *
4820 * @param r a <code>Rectangle</code> containing the dirty region
4821 * @see #isPaintingOrigin()
4822 * @see java.awt.Component#isShowing
4823 * @see RepaintManager#addDirtyRegion
4824 */
4825 public void repaint(Rectangle r) {
4826 repaint(0,r.x,r.y,r.width,r.height);
4827 }
4828
4829
4830 /**
4831 * Supports deferred automatic layout.
4832 * <p>
4833 * Calls <code>invalidate</code> and then adds this component's
4834 * <code>validateRoot</code> to a list of components that need to be
4835 * validated. Validation will occur after all currently pending
4836 * events have been dispatched. In other words after this method
4837 * is called, the first validateRoot (if any) found when walking
4838 * up the containment hierarchy of this component will be validated.
4839 * By default, <code>JRootPane</code>, <code>JScrollPane</code>,
4840 * and <code>JTextField</code> return true
4841 * from <code>isValidateRoot</code>.
4842 * <p>
4843 * This method will automatically be called on this component
4844 * when a property value changes such that size, location, or
4845 * internal layout of this component has been affected. This automatic
4846 * updating differs from the AWT because programs generally no
4847 * longer need to invoke <code>validate</code> to get the contents of the
4848 * GUI to update.
4849 *
4850 * @see java.awt.Component#invalidate
4851 * @see java.awt.Container#validate
4852 * @see #isValidateRoot
4853 * @see RepaintManager#addInvalidComponent
4854 */
4855 public void revalidate() {
4856 if (getParent() == null) {
4857 // Note: We don't bother invalidating here as once added
4858 // to a valid parent invalidate will be invoked (addImpl
4859 // invokes addNotify which will invoke invalidate on the
4860 // new Component). Also, if we do add a check to isValid
4861 // here it can potentially be called before the constructor
4862 // which was causing some people grief.
4863 return;
4864 }
4865 if (SunToolkit.isDispatchThreadForAppContext(this)) {
4866 invalidate();
4867 RepaintManager.currentManager(this).addInvalidComponent(this);
4868 }
4869 else {
4870 // To avoid a flood of Runnables when constructing GUIs off
4871 // the EDT, a flag is maintained as to whether or not
4872 // a Runnable has been scheduled.
4873 if (revalidateRunnableScheduled.getAndSet(true)) {
4874 return;
4875 }
4876 SunToolkit.executeOnEventHandlerThread(this, () -> {
4877 revalidateRunnableScheduled.set(false);
4878 revalidate();
4879 });
4880 }
4881 }
4882
4883 /**
4884 * If this method returns true, <code>revalidate</code> calls by
4885 * descendants of this component will cause the entire tree
4886 * beginning with this root to be validated.
4887 * Returns false by default. <code>JScrollPane</code> overrides
4888 * this method and returns true.
4889 *
4890 * @return always returns false
4891 * @see #revalidate
4892 * @see java.awt.Component#invalidate
4893 * @see java.awt.Container#validate
4894 * @see java.awt.Container#isValidateRoot
4895 */
4896 @Override
4897 public boolean isValidateRoot() {
4898 return false;
4899 }
4900
4901
4902 /**
4903 * Returns true if this component tiles its children -- that is, if
4904 * it can guarantee that the children will not overlap. The
4905 * repainting system is substantially more efficient in this
4906 * common case. <code>JComponent</code> subclasses that can't make this
4907 * guarantee, such as <code>JLayeredPane</code>,
4908 * should override this method to return false.
4909 *
4910 * @return always returns true
4911 */
4912 @BeanProperty(bound = false)
4913 public boolean isOptimizedDrawingEnabled() {
4914 return true;
4915 }
4916
4917 /**
4918 * Returns {@code true} if a paint triggered on a child component should cause
4919 * painting to originate from this Component, or one of its ancestors.
4920 * <p>
4921 * Calling {@link #repaint} or {@link #paintImmediately(int, int, int, int)}
4922 * on a Swing component will result in calling
4923 * the {@link JComponent#paintImmediately(int, int, int, int)} method of
4924 * the first ancestor which {@code isPaintingOrigin()} returns {@code true}, if there are any.
4925 * <p>
4926 * {@code JComponent} subclasses that need to be painted when any of their
4927 * children are repainted should override this method to return {@code true}.
4928 *
4929 * @return always returns {@code false}
4930 *
4931 * @see #paintImmediately(int, int, int, int)
4932 */
4933 protected boolean isPaintingOrigin() {
4934 return false;
4935 }
4936
4937 /**
4938 * Paints the specified region in this component and all of its
4939 * descendants that overlap the region, immediately.
4940 * <p>
4941 * It's rarely necessary to call this method. In most cases it's
4942 * more efficient to call repaint, which defers the actual painting
4943 * and can collapse redundant requests into a single paint call.
4944 * This method is useful if one needs to update the display while
4945 * the current event is being dispatched.
4946 * <p>
4947 * This method is to be overridden when the dirty region needs to be changed
4948 * for components that are painting origins.
4949 *
4950 * @param x the x value of the region to be painted
4951 * @param y the y value of the region to be painted
4952 * @param w the width of the region to be painted
4953 * @param h the height of the region to be painted
4954 * @see #repaint
4955 * @see #isPaintingOrigin()
4956 */
4957 public void paintImmediately(int x,int y,int w, int h) {
4958 Component c = this;
4959 Component parent;
4960
4961 if(!isShowing()) {
4962 return;
4963 }
4964
4965 JComponent paintingOigin = SwingUtilities.getPaintingOrigin(this);
4966 if (paintingOigin != null) {
4967 Rectangle rectangle = SwingUtilities.convertRectangle(
4968 c, new Rectangle(x, y, w, h), paintingOigin);
4969 paintingOigin.paintImmediately(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
4970 return;
4971 }
4972
4973 while(!c.isOpaque()) {
4974 parent = c.getParent();
4975 if(parent != null) {
4976 x += c.getX();
4977 y += c.getY();
4978 c = parent;
4979 } else {
4980 break;
4981 }
4982
4983 if(!(c instanceof JComponent)) {
4984 break;
4985 }
4986 }
4987 if(c instanceof JComponent) {
4988 ((JComponent)c)._paintImmediately(x,y,w,h);
4989 } else {
4990 c.repaint(x,y,w,h);
4991 }
4992 }
4993
4994 /**
4995 * Paints the specified region now.
4996 *
4997 * @param r a <code>Rectangle</code> containing the region to be painted
4998 */
4999 public void paintImmediately(Rectangle r) {
5000 paintImmediately(r.x,r.y,r.width,r.height);
5001 }
5002
5003 /**
5004 * Returns whether this component should be guaranteed to be on top.
5005 * For example, it would make no sense for <code>Menu</code>s to pop up
5006 * under another component, so they would always return true.
5007 * Most components will want to return false, hence that is the default.
5008 *
5009 * @return always returns false
5010 */
5011 // package private
5012 boolean alwaysOnTop() {
5013 return false;
5014 }
5015
5016 void setPaintingChild(Component paintingChild) {
5017 this.paintingChild = paintingChild;
5018 }
5019
5020 void _paintImmediately(int x, int y, int w, int h) {
5021 Graphics g;
5022 Container c;
5023 Rectangle b;
5024
5025 int tmpX, tmpY, tmpWidth, tmpHeight;
5026 int offsetX=0,offsetY=0;
5027
5028 boolean hasBuffer = false;
5029
5030 JComponent bufferedComponent = null;
5031 JComponent paintingComponent = this;
5032
5033 RepaintManager repaintManager = RepaintManager.currentManager(this);
5034 // parent Container's up to Window or Applet. First container is
5035 // the direct parent. Note that in testing it was faster to
5036 // alloc a new Vector vs keeping a stack of them around, and gc
5037 // seemed to have a minimal effect on this.
5038 java.util.List<Component> path = new java.util.ArrayList<Component>(7);
5039 int pIndex = -1;
5040 int pCount = 0;
5041
5042 tmpX = tmpY = tmpWidth = tmpHeight = 0;
5043
5044 Rectangle paintImmediatelyClip = fetchRectangle();
5045 paintImmediatelyClip.x = x;
5046 paintImmediatelyClip.y = y;
5047 paintImmediatelyClip.width = w;
5048 paintImmediatelyClip.height = h;
5049
5050
5051 // System.out.println("1) ************* in _paintImmediately for " + this);
5052
5053 boolean ontop = alwaysOnTop() && isOpaque();
5054 if (ontop) {
5055 SwingUtilities.computeIntersection(0, 0, getWidth(), getHeight(),
5056 paintImmediatelyClip);
5057 if (paintImmediatelyClip.width == 0) {
5058 recycleRectangle(paintImmediatelyClip);
5059 return;
5060 }
5061 }
5062 Component child;
5063 for (c = this, child = null;
5064 c != null && !(c instanceof Window) && !(c instanceof Applet);
5065 child = c, c = c.getParent()) {
5066 JComponent jc = (c instanceof JComponent) ? (JComponent)c :
5067 null;
5068 path.add(c);
5069 if(!ontop && jc != null && !jc.isOptimizedDrawingEnabled()) {
5070 boolean resetPC;
5071
5072 // Children of c may overlap, three possible cases for the
5073 // painting region:
5074 // . Completely obscured by an opaque sibling, in which
5075 // case there is no need to paint.
5076 // . Partially obscured by a sibling: need to start
5077 // painting from c.
5078 // . Otherwise we aren't obscured and thus don't need to
5079 // start painting from parent.
5080 if (c != this) {
5081 if (jc.isPaintingOrigin()) {
5082 resetPC = true;
5083 }
5084 else {
5085 Component[] children = c.getComponents();
5086 int i = 0;
5087 for (; i<children.length; i++) {
5088 if (children[i] == child) break;
5089 }
5090 switch (jc.getObscuredState(i,
5091 paintImmediatelyClip.x,
5092 paintImmediatelyClip.y,
5093 paintImmediatelyClip.width,
5094 paintImmediatelyClip.height)) {
5095 case NOT_OBSCURED:
5096 resetPC = false;
5097 break;
5098 case COMPLETELY_OBSCURED:
5099 recycleRectangle(paintImmediatelyClip);
5100 return;
5101 default:
5102 resetPC = true;
5103 break;
5104 }
5105 }
5106 }
5107 else {
5108 resetPC = false;
5109 }
5110
5111 if (resetPC) {
5112 // Get rid of any buffer since we draw from here and
5113 // we might draw something larger
5114 paintingComponent = jc;
5115 pIndex = pCount;
5116 offsetX = offsetY = 0;
5117 hasBuffer = false;
5118 }
5119 }
5120 pCount++;
5121
5122 // look to see if the parent (and therefor this component)
5123 // is double buffered
5124 if(repaintManager.isDoubleBufferingEnabled() && jc != null &&
5125 jc.isDoubleBuffered()) {
5126 hasBuffer = true;
5127 bufferedComponent = jc;
5128 }
5129
5130 // if we aren't on top, include the parent's clip
5131 if (!ontop) {
5132 int bx = c.getX();
5133 int by = c.getY();
5134 tmpWidth = c.getWidth();
5135 tmpHeight = c.getHeight();
5136 SwingUtilities.computeIntersection(tmpX,tmpY,tmpWidth,tmpHeight,paintImmediatelyClip);
5137 paintImmediatelyClip.x += bx;
5138 paintImmediatelyClip.y += by;
5139 offsetX += bx;
5140 offsetY += by;
5141 }
5142 }
5143
5144 // If the clip width or height is negative, don't bother painting
5145 if(c == null || !c.isDisplayable() ||
5146 paintImmediatelyClip.width <= 0 ||
5147 paintImmediatelyClip.height <= 0) {
5148 recycleRectangle(paintImmediatelyClip);
5149 return;
5150 }
5151
5152 paintingComponent.setFlag(IS_REPAINTING, true);
5153
5154 paintImmediatelyClip.x -= offsetX;
5155 paintImmediatelyClip.y -= offsetY;
5156
5157 // Notify the Components that are going to be painted of the
5158 // child component to paint to.
5159 if(paintingComponent != this) {
5160 Component comp;
5161 int i = pIndex;
5162 for(; i > 0 ; i--) {
5163 comp = path.get(i);
5164 if(comp instanceof JComponent) {
5165 ((JComponent)comp).setPaintingChild(path.get(i-1));
5166 }
5167 }
5168 }
5169 try {
5170 if ((g = safelyGetGraphics(paintingComponent, c)) != null) {
5171 try {
5172 if (hasBuffer) {
5173 RepaintManager rm = RepaintManager.currentManager(
5174 bufferedComponent);
5175 rm.beginPaint();
5176 try {
5177 rm.paint(paintingComponent, bufferedComponent, g,
5178 paintImmediatelyClip.x,
5179 paintImmediatelyClip.y,
5180 paintImmediatelyClip.width,
5181 paintImmediatelyClip.height);
5182 } finally {
5183 rm.endPaint();
5184 }
5185 } else {
5186 g.setClip(paintImmediatelyClip.x, paintImmediatelyClip.y,
5187 paintImmediatelyClip.width, paintImmediatelyClip.height);
5188 paintingComponent.paint(g);
5189 }
5190 } finally {
5191 g.dispose();
5192 }
5193 }
5194 }
5195 finally {
5196 // Reset the painting child for the parent components.
5197 if(paintingComponent != this) {
5198 Component comp;
5199 int i = pIndex;
5200 for(; i > 0 ; i--) {
5201 comp = path.get(i);
5202 if(comp instanceof JComponent) {
5203 ((JComponent)comp).setPaintingChild(null);
5204 }
5205 }
5206 }
5207 paintingComponent.setFlag(IS_REPAINTING, false);
5208 }
5209 recycleRectangle(paintImmediatelyClip);
5210 }
5211
5212 /**
5213 * Paints to the specified graphics. This does not set the clip and it
5214 * does not adjust the Graphics in anyway, callers must do that first.
5215 * This method is package-private for RepaintManager.PaintManager and
5216 * its subclasses to call, it is NOT intended for general use outside
5217 * of that.
5218 */
5219 void paintToOffscreen(Graphics g, int x, int y, int w, int h, int maxX,
5220 int maxY) {
5221 try {
5222 setFlag(ANCESTOR_USING_BUFFER, true);
5223 if ((y + h) < maxY || (x + w) < maxX) {
5224 setFlag(IS_PAINTING_TILE, true);
5225 }
5226 if (getFlag(IS_REPAINTING)) {
5227 // Called from paintImmediately (RepaintManager) to fill
5228 // repaint request
5229 paint(g);
5230 } else {
5231 // Called from paint() (AWT) to repair damage
5232 if(!rectangleIsObscured(x, y, w, h)) {
5233 paintComponent(g);
5234 paintBorder(g);
5235 }
5236 paintChildren(g);
5237 }
5238 } finally {
5239 setFlag(ANCESTOR_USING_BUFFER, false);
5240 setFlag(IS_PAINTING_TILE, false);
5241 }
5242 }
5243
5244 /**
5245 * Returns whether or not the region of the specified component is
5246 * obscured by a sibling.
5247 *
5248 * @return NOT_OBSCURED if non of the siblings above the Component obscure
5249 * it, COMPLETELY_OBSCURED if one of the siblings completely
5250 * obscures the Component or PARTIALLY_OBSCURED if the Component is
5251 * only partially obscured.
5252 */
5253 private int getObscuredState(int compIndex, int x, int y, int width,
5254 int height) {
5255 int retValue = NOT_OBSCURED;
5256 Rectangle tmpRect = fetchRectangle();
5257
5258 for (int i = compIndex - 1 ; i >= 0 ; i--) {
5259 Component sibling = getComponent(i);
5260 if (!sibling.isVisible()) {
5261 continue;
5262 }
5263 Rectangle siblingRect;
5264 boolean opaque;
5265 if (sibling instanceof JComponent) {
5266 opaque = sibling.isOpaque();
5267 if (!opaque) {
5268 if (retValue == PARTIALLY_OBSCURED) {
5269 continue;
5270 }
5271 }
5272 }
5273 else {
5274 opaque = true;
5275 }
5276 siblingRect = sibling.getBounds(tmpRect);
5277 if (opaque && x >= siblingRect.x && (x + width) <=
5278 (siblingRect.x + siblingRect.width) &&
5279 y >= siblingRect.y && (y + height) <=
5280 (siblingRect.y + siblingRect.height)) {
5281 recycleRectangle(tmpRect);
5282 return COMPLETELY_OBSCURED;
5283 }
5284 else if (retValue == NOT_OBSCURED &&
5285 !((x + width <= siblingRect.x) ||
5286 (y + height <= siblingRect.y) ||
5287 (x >= siblingRect.x + siblingRect.width) ||
5288 (y >= siblingRect.y + siblingRect.height))) {
5289 retValue = PARTIALLY_OBSCURED;
5290 }
5291 }
5292 recycleRectangle(tmpRect);
5293 return retValue;
5294 }
5295
5296 /**
5297 * Returns true, which implies that before checking if a child should
5298 * be painted it is first check that the child is not obscured by another
5299 * sibling. This is only checked if <code>isOptimizedDrawingEnabled</code>
5300 * returns false.
5301 *
5302 * @return always returns true
5303 */
5304 boolean checkIfChildObscuredBySibling() {
5305 return true;
5306 }
5307
5308
5309 private void setFlag(int aFlag, boolean aValue) {
5310 if(aValue) {
5311 flags |= (1 << aFlag);
5312 } else {
5313 flags &= ~(1 << aFlag);
5314 }
5315 }
5316 private boolean getFlag(int aFlag) {
5317 int mask = (1 << aFlag);
5318 return ((flags & mask) == mask);
5319 }
5320 // These functions must be static so that they can be called from
5321 // subclasses inside the package, but whose inheritance hierarhcy includes
5322 // classes outside of the package below JComponent (e.g., JTextArea).
5323 static void setWriteObjCounter(JComponent comp, byte count) {
5324 comp.flags = (comp.flags & ~(0xFF << WRITE_OBJ_COUNTER_FIRST)) |
5325 (count << WRITE_OBJ_COUNTER_FIRST);
5326 }
5327 static byte getWriteObjCounter(JComponent comp) {
5328 return (byte)((comp.flags >> WRITE_OBJ_COUNTER_FIRST) & 0xFF);
5329 }
5330
5331 /** Buffering **/
5332
5333 /**
5334 * Sets whether this component should use a buffer to paint.
5335 * If set to true, all the drawing from this component will be done
5336 * in an offscreen painting buffer. The offscreen painting buffer will
5337 * the be copied onto the screen.
5338 * If a <code>Component</code> is buffered and one of its ancestor
5339 * is also buffered, the ancestor buffer will be used.
5340 *
5341 * @param aFlag if true, set this component to be double buffered
5342 */
5343 public void setDoubleBuffered(boolean aFlag) {
5344 setFlag(IS_DOUBLE_BUFFERED,aFlag);
5345 }
5346
5347 /**
5348 * Returns whether this component should use a buffer to paint.
5349 *
5350 * @return true if this component is double buffered, otherwise false
5351 */
5352 public boolean isDoubleBuffered() {
5353 return getFlag(IS_DOUBLE_BUFFERED);
5354 }
5355
5356 /**
5357 * Returns the <code>JRootPane</code> ancestor for this component.
5358 *
5359 * @return the <code>JRootPane</code> that contains this component,
5360 * or <code>null</code> if no <code>JRootPane</code> is found
5361 */
5362 @BeanProperty(bound = false)
5363 public JRootPane getRootPane() {
5364 return SwingUtilities.getRootPane(this);
5365 }
5366
5367
5368 /** Serialization **/
5369
5370 /**
5371 * This is called from Component by way of reflection. Do NOT change
5372 * the name unless you change the code in Component as well.
5373 */
5374 void compWriteObjectNotify() {
5375 byte count = JComponent.getWriteObjCounter(this);
5376 JComponent.setWriteObjCounter(this, (byte)(count + 1));
5377 if (count != 0) {
5378 return;
5379 }
5380
5381 uninstallUIAndProperties();
5382
5383 /* JTableHeader is in a separate package, which prevents it from
5384 * being able to override this package-private method the way the
5385 * other components can. We don't want to make this method protected
5386 * because it would introduce public-api for a less-than-desirable
5387 * serialization scheme, so we compromise with this 'instanceof' hack
5388 * for now.
5389 */
5390 if (getToolTipText() != null ||
5391 this instanceof javax.swing.table.JTableHeader) {
5392 ToolTipManager.sharedInstance().unregisterComponent(JComponent.this);
5393 }
5394 }
5395
5396 /**
5397 * This object is the <code>ObjectInputStream</code> callback
5398 * that's called after a complete graph of objects (including at least
5399 * one <code>JComponent</code>) has been read.
5400 * It sets the UI property of each Swing component
5401 * that was read to the current default with <code>updateUI</code>.
5402 * <p>
5403 * As each component is read in we keep track of the current set of
5404 * root components here, in the roots vector. Note that there's only one
5405 * <code>ReadObjectCallback</code> per <code>ObjectInputStream</code>,
5406 * they're stored in the static <code>readObjectCallbacks</code>
5407 * hashtable.
5408 *
5409 * @see java.io.ObjectInputStream#registerValidation
5410 * @see SwingUtilities#updateComponentTreeUI
5411 */
5412 private class ReadObjectCallback implements ObjectInputValidation
5413 {
5414 private final Vector<JComponent> roots = new Vector<JComponent>(1);
5415 private final ObjectInputStream inputStream;
5416
5417 ReadObjectCallback(ObjectInputStream s) throws Exception {
5418 inputStream = s;
5419 s.registerValidation(this, 0);
5420 }
5421
5422 /**
5423 * This is the method that's called after the entire graph
5424 * of objects has been read in. It initializes
5425 * the UI property of all of the copmonents with
5426 * <code>SwingUtilities.updateComponentTreeUI</code>.
5427 */
5428 public void validateObject() throws InvalidObjectException {
5429 try {
5430 for (JComponent root : roots) {
5431 SwingUtilities.updateComponentTreeUI(root);
5432 }
5433 }
5434 finally {
5435 readObjectCallbacks.remove(inputStream);
5436 }
5437 }
5438
5439 /**
5440 * If <code>c</code> isn't a descendant of a component we've already
5441 * seen, then add it to the roots <code>Vector</code>.
5442 *
5443 * @param c the <code>JComponent</code> to add
5444 */
5445 private void registerComponent(JComponent c)
5446 {
5447 /* If the Component c is a descendant of one of the
5448 * existing roots (or it IS an existing root), we're done.
5449 */
5450 for (JComponent root : roots) {
5451 for(Component p = c; p != null; p = p.getParent()) {
5452 if (p == root) {
5453 return;
5454 }
5455 }
5456 }
5457
5458 /* Otherwise: if Component c is an ancestor of any of the
5459 * existing roots then remove them and add c (the "new root")
5460 * to the roots vector.
5461 */
5462 for(int i = 0; i < roots.size(); i++) {
5463 JComponent root = roots.elementAt(i);
5464 for(Component p = root.getParent(); p != null; p = p.getParent()) {
5465 if (p == c) {
5466 roots.removeElementAt(i--); // !!
5467 break;
5468 }
5469 }
5470 }
5471
5472 roots.addElement(c);
5473 }
5474 }
5475
5476
5477 /**
5478 * We use the <code>ObjectInputStream</code> "registerValidation"
5479 * callback to update the UI for the entire tree of components
5480 * after they've all been read in.
5481 *
5482 * @param s the <code>ObjectInputStream</code> from which to read
5483 */
5484 private void readObject(ObjectInputStream s)
5485 throws IOException, ClassNotFoundException
5486 {
5487 ObjectInputStream.GetField f = s.readFields();
5488
5489 isAlignmentXSet = f.get("isAlignmentXSet", false);
5490 alignmentX = validateAlignment(f.get("alignmentX", 0f));
5491 isAlignmentYSet = f.get("isAlignmentYSet", false);
5492 alignmentY = validateAlignment(f.get("alignmentY", 0f));
5493 listenerList = (EventListenerList) f.get("listenerList", null);
5494 vetoableChangeSupport = (VetoableChangeSupport) f.get("vetoableChangeSupport", null);
5495 autoscrolls = f.get("autoscrolls", false);
5496 border = (Border) f.get("border", null);
5497 flags = f.get("flags", 0);
5498 inputVerifier = (InputVerifier) f.get("inputVerifier", null);
5499 verifyInputWhenFocusTarget = f.get("verifyInputWhenFocusTarget", false);
5500 popupMenu = (JPopupMenu) f.get("popupMenu", null);
5501 focusInputMap = (InputMap) f.get("focusInputMap", null);
5502 ancestorInputMap = (InputMap) f.get("ancestorInputMap", null);
5503 windowInputMap = (ComponentInputMap) f.get("windowInputMap", null);
5504 actionMap = (ActionMap) f.get("actionMap", null);
5505
5506 /* If there's no ReadObjectCallback for this stream yet, that is, if
5507 * this is the first call to JComponent.readObject() for this
5508 * graph of objects, then create a callback and stash it
5509 * in the readObjectCallbacks table. Note that the ReadObjectCallback
5510 * constructor takes care of calling s.registerValidation().
5511 */
5512 ReadObjectCallback cb = readObjectCallbacks.get(s);
5513 if (cb == null) {
5514 try {
5515 readObjectCallbacks.put(s, cb = new ReadObjectCallback(s));
5516 }
5517 catch (Exception e) {
5518 throw new IOException(e.toString());
5519 }
5520 }
5521 cb.registerComponent(this);
5522
5523 // Read back the client properties.
5524 int cpCount = s.readInt();
5525 if (cpCount > 0) {
5526 clientProperties = new ArrayTable();
5527 for (int counter = 0; counter < cpCount; counter++) {
5528 clientProperties.put(s.readObject(),
5529 s.readObject());
5530 }
5531 }
5532 if (getToolTipText() != null) {
5533 ToolTipManager.sharedInstance().registerComponent(this);
5534 }
5535 setWriteObjCounter(this, (byte)0);
5536 revalidateRunnableScheduled = new AtomicBoolean(false);
5537 }
5538
5539
5540 /**
5541 * Before writing a <code>JComponent</code> to an
5542 * <code>ObjectOutputStream</code> we temporarily uninstall its UI.
5543 * This is tricky to do because we want to uninstall
5544 * the UI before any of the <code>JComponent</code>'s children
5545 * (or its <code>LayoutManager</code> etc.) are written,
5546 * and we don't want to restore the UI until the most derived
5547 * <code>JComponent</code> subclass has been stored.
5548 *
5549 * @param s the <code>ObjectOutputStream</code> in which to write
5550 */
5551 private void writeObject(ObjectOutputStream s) throws IOException {
5552 s.defaultWriteObject();
5553 if (getUIClassID().equals(uiClassID)) {
5554 byte count = JComponent.getWriteObjCounter(this);
5555 JComponent.setWriteObjCounter(this, --count);
5556 if (count == 0 && ui != null) {
5557 ui.installUI(this);
5558 }
5559 }
5560 ArrayTable.writeArrayTable(s, clientProperties);
5561 }
5562
5563
5564 /**
5565 * Returns a string representation of this <code>JComponent</code>.
5566 * This method
5567 * is intended to be used only for debugging purposes, and the
5568 * content and format of the returned string may vary between
5569 * implementations. The returned string may be empty but may not
5570 * be <code>null</code>.
5571 *
5572 * @return a string representation of this <code>JComponent</code>
5573 */
5574 protected String paramString() {
5575 String preferredSizeString = (isPreferredSizeSet() ?
5576 getPreferredSize().toString() : "");
5577 String minimumSizeString = (isMinimumSizeSet() ?
5578 getMinimumSize().toString() : "");
5579 String maximumSizeString = (isMaximumSizeSet() ?
5580 getMaximumSize().toString() : "");
5581 String borderString = (border == null ? ""
5582 : (border == this ? "this" : border.toString()));
5583
5584 return super.paramString() +
5585 ",alignmentX=" + alignmentX +
5586 ",alignmentY=" + alignmentY +
5587 ",border=" + borderString +
5588 ",flags=" + flags + // should beef this up a bit
5589 ",maximumSize=" + maximumSizeString +
5590 ",minimumSize=" + minimumSizeString +
5591 ",preferredSize=" + preferredSizeString;
5592 }
5593
5594 /**
5595 * {@inheritDoc}
5596 */
5597 @Override
5598 @Deprecated
5599 public void hide() {
5600 boolean showing = isShowing();
5601 super.hide();
5602 if (showing) {
5603 Container parent = getParent();
5604 if (parent != null) {
5605 Rectangle r = getBounds();
5606 parent.repaint(r.x, r.y, r.width, r.height);
5607 }
5608 revalidate();
5609 }
5610 }
5611
5612 }
--- EOF ---