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

Save This Page
Home » openjdk-7 » javax » swing » [javadoc | source]