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