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