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