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