001    /* JComponent.java -- Every component in swing inherits from this class.
002       Copyright (C) 2002, 2004, 2005, 2006,  Free Software Foundation, Inc.
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010    
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    
039    package javax.swing;
040    
041    import java.applet.Applet;
042    import java.awt.AWTEvent;
043    import java.awt.Color;
044    import java.awt.Component;
045    import java.awt.Container;
046    import java.awt.Dimension;
047    import java.awt.EventQueue;
048    import java.awt.FocusTraversalPolicy;
049    import java.awt.Font;
050    import java.awt.Graphics;
051    import java.awt.Image;
052    import java.awt.Insets;
053    import java.awt.Point;
054    import java.awt.Rectangle;
055    import java.awt.Window;
056    import java.awt.dnd.DropTarget;
057    import java.awt.event.ActionEvent;
058    import java.awt.event.ActionListener;
059    import java.awt.event.ContainerEvent;
060    import java.awt.event.ContainerListener;
061    import java.awt.event.FocusEvent;
062    import java.awt.event.FocusListener;
063    import java.awt.event.KeyEvent;
064    import java.awt.event.MouseEvent;
065    import java.awt.peer.LightweightPeer;
066    import java.beans.PropertyChangeEvent;
067    import java.beans.PropertyChangeListener;
068    import java.beans.PropertyVetoException;
069    import java.beans.VetoableChangeListener;
070    import java.beans.VetoableChangeSupport;
071    import java.io.Serializable;
072    import java.util.ArrayList;
073    import java.util.EventListener;
074    import java.util.Hashtable;
075    import java.util.Locale;
076    import java.util.Set;
077    
078    import javax.accessibility.Accessible;
079    import javax.accessibility.AccessibleContext;
080    import javax.accessibility.AccessibleExtendedComponent;
081    import javax.accessibility.AccessibleKeyBinding;
082    import javax.accessibility.AccessibleRole;
083    import javax.accessibility.AccessibleState;
084    import javax.accessibility.AccessibleStateSet;
085    import javax.swing.border.Border;
086    import javax.swing.border.CompoundBorder;
087    import javax.swing.border.TitledBorder;
088    import javax.swing.event.AncestorEvent;
089    import javax.swing.event.AncestorListener;
090    import javax.swing.event.EventListenerList;
091    import javax.swing.plaf.ComponentUI;
092    
093    /**
094     * The base class of all Swing components.
095     * It contains generic methods to manage events, properties and sizes. Actual
096     * drawing of the component is channeled to a look-and-feel class that is
097     * implemented elsewhere.
098     *
099     * @author Ronald Veldema (rveldema&064;cs.vu.nl)
100     * @author Graydon Hoare (graydon&064;redhat.com)
101     */
102    public abstract class JComponent extends Container implements Serializable
103    {
104      private static final long serialVersionUID = -7908749299918704233L;
105    
106      /** 
107       * The accessible context of this <code>JComponent</code>.
108       */
109      protected AccessibleContext accessibleContext;
110    
111      /**
112       * Basic accessibility support for <code>JComponent</code> derived
113       * widgets.
114       */
115      public abstract class AccessibleJComponent 
116        extends AccessibleAWTContainer
117        implements AccessibleExtendedComponent
118      {
119        /**
120         * Receives notification if the focus on the JComponent changes and
121         * fires appropriate PropertyChangeEvents to listeners registered with
122         * the AccessibleJComponent.
123         */
124        protected class AccessibleFocusHandler 
125          implements FocusListener
126        {
127          /**
128           * Creates a new AccessibleFocusHandler.
129           */
130          protected AccessibleFocusHandler()
131          {
132            // Nothing to do here.
133          }
134    
135          /**
136           * Receives notification when the JComponent gained focus and fires
137           * a PropertyChangeEvent to listeners registered on the
138           * AccessibleJComponent with a property name of
139           * {@link AccessibleContext#ACCESSIBLE_STATE_PROPERTY} and a new value
140           * of {@link AccessibleState#FOCUSED}.
141           */
142          public void focusGained(FocusEvent event)
143          {
144            AccessibleJComponent.this.firePropertyChange
145              (AccessibleContext.ACCESSIBLE_STATE_PROPERTY, null,
146               AccessibleState.FOCUSED);
147          }
148    
149          /**
150           * Receives notification when the JComponent lost focus and fires
151           * a PropertyChangeEvent to listeners registered on the
152           * AccessibleJComponent with a property name of
153           * {@link AccessibleContext#ACCESSIBLE_STATE_PROPERTY} and an old value
154           * of {@link AccessibleState#FOCUSED}.
155           */
156          public void focusLost(FocusEvent valevent)
157          {
158            AccessibleJComponent.this.firePropertyChange
159              (AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
160               AccessibleState.FOCUSED, null);
161          }
162        }
163    
164        /**
165         * Receives notification if there are child components are added or removed
166         * from the JComponent and fires appropriate PropertyChangeEvents to
167         * interested listeners on the AccessibleJComponent.
168         */
169        protected class AccessibleContainerHandler 
170          implements ContainerListener
171        {
172          /**
173           * Creates a new AccessibleContainerHandler.
174           */
175          protected AccessibleContainerHandler()
176          {
177            // Nothing to do here.
178          }
179    
180          /**
181           * Receives notification when a child component is added to the
182           * JComponent and fires a PropertyChangeEvent on listeners registered
183           * with the AccessibleJComponent with a property name of
184           * {@link AccessibleContext#ACCESSIBLE_CHILD_PROPERTY}.
185           *
186           * @param event the container event
187           */
188          public void componentAdded(ContainerEvent event)
189          {
190            Component c = event.getChild();
191            if (c != null && c instanceof Accessible)
192              {
193                AccessibleContext childCtx = c.getAccessibleContext();
194                AccessibleJComponent.this.firePropertyChange
195                  (AccessibleContext.ACCESSIBLE_CHILD_PROPERTY, null, childCtx);
196              }
197          }
198    
199          /**
200           * Receives notification when a child component is removed from the
201           * JComponent and fires a PropertyChangeEvent on listeners registered
202           * with the AccessibleJComponent with a property name of
203           * {@link AccessibleContext#ACCESSIBLE_CHILD_PROPERTY}.
204           *
205           * @param event the container event
206           */
207          public void componentRemoved(ContainerEvent event)
208          {
209            Component c = event.getChild();
210            if (c != null && c instanceof Accessible)
211              {
212                AccessibleContext childCtx = c.getAccessibleContext();
213                AccessibleJComponent.this.firePropertyChange
214                  (AccessibleContext.ACCESSIBLE_CHILD_PROPERTY, childCtx, null);
215              }
216          }
217        }
218    
219        private static final long serialVersionUID = -7047089700479897799L;
220    
221        /**
222         * Receives notification when a child component is added to the
223         * JComponent and fires a PropertyChangeEvent on listeners registered
224         * with the AccessibleJComponent.
225         *
226         * @specnote AccessibleAWTContainer has a protected field with the same
227         *           name. Looks like a bug or nasty misdesign to me.
228         */
229        protected ContainerListener accessibleContainerHandler;
230    
231        /**
232         * Receives notification if the focus on the JComponent changes and
233         * fires appropriate PropertyChangeEvents to listeners registered with
234         * the AccessibleJComponent.
235         *
236         * @specnote AccessibleAWTComponent has a protected field
237         *           accessibleAWTFocusHandler. Looks like a bug or nasty misdesign
238         *           to me.
239         */
240        protected FocusListener accessibleFocusHandler;
241    
242        /**
243         * Creates a new AccessibleJComponent.
244         */
245        protected AccessibleJComponent()
246        {
247          // Nothing to do here.
248        }
249    
250        /**
251         * Adds a property change listener to the list of registered listeners.
252         *
253         * This sets up the {@link #accessibleContainerHandler} and
254         * {@link #accessibleFocusHandler} fields and calls
255         * <code>super.addPropertyChangeListener(listener)</code>.
256         *
257         * @param listener the listener to add
258         */
259        public void addPropertyChangeListener(PropertyChangeListener listener)
260        {
261          // Tests seem to indicate that this method also sets up the other two
262          // handlers.
263          if (accessibleContainerHandler == null)
264            {
265              accessibleContainerHandler = new AccessibleContainerHandler();
266              addContainerListener(accessibleContainerHandler);
267            }
268          if (accessibleFocusHandler == null)
269            {
270              accessibleFocusHandler = new AccessibleFocusHandler();
271              addFocusListener(accessibleFocusHandler);
272            }
273          super.addPropertyChangeListener(listener);
274        }
275    
276        /**
277         * Removes a property change listener from the list of registered listeners.
278         *
279         * This uninstalls the {@link #accessibleContainerHandler} and
280         * {@link #accessibleFocusHandler} fields and calls
281         * <code>super.removePropertyChangeListener(listener)</code>.
282         *
283         * @param listener the listener to remove
284         */
285        public void removePropertyChangeListener(PropertyChangeListener listener)
286        {
287          // Tests seem to indicate that this method also resets the other two
288          // handlers.
289          if (accessibleContainerHandler != null)
290            {
291              removeContainerListener(accessibleContainerHandler);
292              accessibleContainerHandler = null;
293            }
294          if (accessibleFocusHandler != null)
295            {
296              removeFocusListener(accessibleFocusHandler);
297              accessibleFocusHandler = null;
298            }
299          super.removePropertyChangeListener(listener);
300        }
301    
302        /**
303         * Returns the number of accessible children of this object.
304         *
305         * @return  the number of accessible children of this object
306         */
307        public int getAccessibleChildrenCount()
308        {
309          // TODO: The functionality should be performed in the superclass.
310          // Find out why this is overridden. However, it is very well possible
311          // that this is left over from times when there was no such superclass
312          // method.
313          return super.getAccessibleChildrenCount();
314        }
315    
316        /**
317         * Returns the accessible child component at index <code>i</code>.
318         *
319         * @param i the index of the accessible child to return
320         *
321         * @return the accessible child component at index <code>i</code>
322         */
323        public Accessible getAccessibleChild(int i)
324        {
325          // TODO: The functionality should be performed in the superclass.
326          // Find out why this is overridden. However, it is very well possible
327          // that this is left over from times when there was no such superclass
328          // method.
329          return super.getAccessibleChild(i);
330        }
331    
332        /**
333         * Returns the accessible state set of this component.
334         *
335         * @return the accessible state set of this component
336         */
337        public AccessibleStateSet getAccessibleStateSet()
338        {
339          // Note: While the java.awt.Component has an 'opaque' property, it
340          // seems that it is not added to the accessible state set there, even
341          // if this property is true. However, it is handled for JComponent, so
342          // we add it here.
343          AccessibleStateSet state = super.getAccessibleStateSet();
344          if (isOpaque())
345            state.add(AccessibleState.OPAQUE);
346          return state;
347        }
348    
349        /**
350         * Returns the localized name for this object. Generally this should
351         * almost never return {@link Component#getName()} since that is not
352         * a localized name. If the object is some kind of text component (like
353         * a menu item), then the value of the object may be returned. Also, if
354         * the object has a tooltip, the value of the tooltip may also be
355         * appropriate.
356         *
357         * @return the localized name for this object or <code>null</code> if this
358         *         object has no name
359         */
360        public String getAccessibleName()
361        {
362          String name = super.getAccessibleName();
363    
364          // There are two fallbacks provided by the JComponent in the case the
365          // superclass returns null:
366          // - If the component is inside a titled border, then it inherits the
367          //   name from the border title.
368          // - If the component is not inside a titled border but has a label
369          //   (via JLabel.setLabelFor()), then it gets the name from the label's
370          //   accessible context.
371    
372          if (name == null)
373            {
374              name = getTitledBorderText();
375            }
376    
377          if (name == null)
378            {
379              Object l = getClientProperty(JLabel.LABEL_PROPERTY);
380              if (l instanceof Accessible)
381                {
382                  AccessibleContext labelCtx =
383                    ((Accessible) l).getAccessibleContext();
384                  name = labelCtx.getAccessibleName();
385                }
386            }
387    
388          return name;
389        }
390    
391        /**
392         * Returns the localized description of this object.
393         *
394         * @return the localized description of this object or <code>null</code>
395         *         if this object has no description
396         */
397        public String getAccessibleDescription()
398        {
399          // There are two fallbacks provided by the JComponent in the case the
400          // superclass returns null:
401          // - If the component has a tooltip, then inherit the description from
402          //   the tooltip.
403          // - If the component is not inside a titled border but has a label
404          //   (via JLabel.setLabelFor()), then it gets the name from the label's
405          //   accessible context.
406          String descr = super.getAccessibleDescription();
407    
408          if (descr == null)
409            {
410              descr = getToolTipText();
411            }
412    
413          if (descr == null)
414            {
415              Object l = getClientProperty(JLabel.LABEL_PROPERTY);
416              if (l instanceof Accessible)
417                {
418                  AccessibleContext labelCtx =
419                    ((Accessible) l).getAccessibleContext();
420                  descr = labelCtx.getAccessibleName();
421                }
422            }
423    
424          return descr;
425        }
426    
427        /**
428         * Returns the accessible role of this component.
429         *
430         * @return the accessible role of this component
431         *
432         * @see AccessibleRole
433         */
434        public AccessibleRole getAccessibleRole()
435        {
436          return AccessibleRole.SWING_COMPONENT;
437        }
438    
439        /**
440         * Recursivly searches a border hierarchy (starting at <code>border) for
441         * a titled border and returns the title if one is found, <code>null</code>
442         * otherwise.
443         *
444         * @param border the border to start search from
445         *
446         * @return the border title of a possibly found titled border
447         */
448        protected String getBorderTitle(Border border)
449        {
450          String title = null;
451          if (border instanceof CompoundBorder)
452            {
453              CompoundBorder compound = (CompoundBorder) border;
454              Border inner = compound.getInsideBorder();
455              title = getBorderTitle(inner);
456              if (title == null)
457                {
458                  Border outer = compound.getOutsideBorder();
459                  title = getBorderTitle(outer);
460                }
461            }
462          else if (border instanceof TitledBorder)
463            {
464              TitledBorder titled = (TitledBorder) border;
465              title = titled.getTitle(); 
466            }
467          return title;
468        }
469    
470        /**
471         * Returns the tooltip text for this accessible component.
472         *
473         * @return the tooltip text for this accessible component
474         */
475        public String getToolTipText()
476        {
477          return JComponent.this.getToolTipText();
478        }
479    
480        /**
481         * Returns the title of the border of this accessible component if
482         * this component has a titled border, otherwise returns <code>null</code>.
483         *
484         * @return the title of the border of this accessible component if
485         *         this component has a titled border, otherwise returns
486         *         <code>null</code>
487         */
488        public String getTitledBorderText()
489        {
490          return getBorderTitle(getBorder()); 
491        }
492    
493        /**
494         * Returns the keybindings associated with this accessible component or
495         * <code>null</code> if the component does not support key bindings.
496         *
497         * @return the keybindings associated with this accessible component
498         */
499        public AccessibleKeyBinding getAccessibleKeyBinding()
500        {
501          // The reference implementation seems to always return null here,
502          // independent of the key bindings of the JComponent. So do we.
503          return null;
504        }
505      }
506    
507      /**
508       * A value between 0.0 and 1.0 indicating the preferred horizontal
509       * alignment of the component, relative to its siblings. The values
510       * {@link #LEFT_ALIGNMENT}, {@link #CENTER_ALIGNMENT}, and {@link
511       * #RIGHT_ALIGNMENT} can also be used, as synonyms for <code>0.0</code>,
512       * <code>0.5</code>, and <code>1.0</code>, respectively. Not all layout
513       * managers use this property.
514       *
515       * @see #getAlignmentX
516       * @see #setAlignmentX
517       * @see javax.swing.OverlayLayout
518       * @see javax.swing.BoxLayout
519       */
520      float alignmentX = -1.0F;
521    
522      /**
523       * A value between 0.0 and 1.0 indicating the preferred vertical
524       * alignment of the component, relative to its siblings. The values
525       * {@link #TOP_ALIGNMENT}, {@link #CENTER_ALIGNMENT}, and {@link
526       * #BOTTOM_ALIGNMENT} can also be used, as synonyms for <code>0.0</code>,
527       * <code>0.5</code>, and <code>1.0</code>, respectively. Not all layout
528       * managers use this property.
529       *
530       * @see #getAlignmentY
531       * @see #setAlignmentY
532       * @see javax.swing.OverlayLayout
533       * @see javax.swing.BoxLayout
534       */
535      float alignmentY = -1.0F;
536    
537      /** 
538       * The border painted around this component.
539       * 
540       * @see #paintBorder
541       */
542      Border border;
543    
544      /**
545       * The popup menu for the component.
546       * 
547       * @see #getComponentPopupMenu()
548       * @see #setComponentPopupMenu(JPopupMenu)
549       */
550      JPopupMenu componentPopupMenu;
551       
552      /**
553       * A flag that controls whether the {@link #getComponentPopupMenu()} method
554       * looks to the component's parent when the <code>componentPopupMenu</code>
555       * field is <code>null</code>.
556       */
557      boolean inheritsPopupMenu;
558      
559      /** 
560       * <p>Whether to double buffer this component when painting. This flag
561       * should generally be <code>true</code>, to ensure good painting
562       * performance.</p>
563       *
564       * <p>All children of a double buffered component are painted into the
565       * double buffer automatically, so only the top widget in a window needs
566       * to be double buffered.</p>
567       *
568       * @see #setDoubleBuffered
569       * @see #isDoubleBuffered
570       * @see #paint
571       */
572      boolean doubleBuffered = true;
573    
574      /**
575       * A set of flags indicating which debugging graphics facilities should
576       * be enabled on this component. The values should be a combination of
577       * {@link DebugGraphics#NONE_OPTION}, {@link DebugGraphics#LOG_OPTION},
578       * {@link DebugGraphics#FLASH_OPTION}, or {@link
579       * DebugGraphics#BUFFERED_OPTION}.
580       *
581       * @see #setDebugGraphicsOptions
582       * @see #getDebugGraphicsOptions
583       * @see DebugGraphics
584       * @see #getComponentGraphics
585       */
586      int debugGraphicsOptions;
587    
588      /** 
589       * <p>This property controls two independent behaviors simultaneously.</p>
590       *
591       * <p>First, it controls whether to fill the background of this widget
592       * when painting its body. This affects calls to {@link
593       * JComponent#paintComponent}, which in turn calls {@link
594       * ComponentUI#update} on the component's {@link #ui} property. If the
595       * component is opaque during this call, the background will be filled
596       * before calling {@link ComponentUI#paint}. This happens merely as a
597       * convenience; you may fill the component's background yourself too,
598       * but there is no need to do so if you will be filling with the same
599       * color.</p>
600       *
601       * <p>Second, it the opaque property informs swing's repaint system
602       * whether it will be necessary to paint the components "underneath" this
603       * component, in Z-order. If the component is opaque, it is considered to
604       * completely occlude components "underneath" it, so they will not be
605       * repainted along with the opaque component.</p>
606       *
607       * <p>The default value for this property is <code>false</code>, but most
608       * components will want to set it to <code>true</code> when installing UI
609       * defaults in {@link ComponentUI#installUI}.</p>
610       *
611       * @see #setOpaque
612       * @see #isOpaque
613       * @see #paintComponent
614       */
615      boolean opaque = false;
616    
617      /** 
618       * The user interface delegate for this component. Event delivery and
619       * repainting of the component are usually delegated to this object. 
620       *
621       * @see #setUI
622       * @see #getUIClassID
623       * @see #updateUI
624       */
625      protected ComponentUI ui;
626    
627      /**
628       * A hint to the focus system that this component should or should not
629       * get focus. If this is <code>false</code>, swing will not try to
630       * request focus on this component; if <code>true</code>, swing might
631       * try to request focus, but the request might fail. Thus it is only 
632       * a hint guiding swing's behavior.
633       *
634       * @see #requestFocus()
635       * @see #isRequestFocusEnabled
636       * @see #setRequestFocusEnabled
637       */
638      boolean requestFocusEnabled;
639    
640      /**
641       * Flag indicating behavior of this component when the mouse is dragged
642       * outside the component and the mouse <em>stops moving</em>. If
643       * <code>true</code>, synthetic mouse events will be delivered on regular
644       * timed intervals, continuing off in the direction the mouse exited the
645       * component, until the mouse is released or re-enters the component.
646       *
647       * @see #setAutoscrolls
648       * @see #getAutoscrolls
649       */
650      boolean autoscrolls = false;
651    
652      /**
653       * Indicates whether the current paint call is already double buffered or
654       * not. 
655       */
656      static boolean paintingDoubleBuffered = false;
657    
658      /**
659       * Indicates whether we are calling paintDoubleBuffered() from
660       * paintImmadiately (RepaintManager) or from paint() (AWT refresh).
661       */
662      static boolean isRepainting = false;
663    
664      /**
665       * Listeners for events other than {@link PropertyChangeEvent} are
666       * handled by this listener list. PropertyChangeEvents are handled in
667       * {@link #changeSupport}.
668       */
669      protected EventListenerList listenerList = new EventListenerList();
670    
671      /**
672       * Handles VetoableChangeEvents.
673       */
674      private VetoableChangeSupport vetoableChangeSupport;
675    
676      /** 
677       * Storage for "client properties", which are key/value pairs associated
678       * with this component by a "client", such as a user application or a
679       * layout manager. This is lazily constructed when the component gets its
680       * first client property.
681       */
682      private Hashtable clientProperties;
683      
684      private InputMap inputMap_whenFocused;
685      private InputMap inputMap_whenAncestorOfFocused;
686      private ComponentInputMap inputMap_whenInFocusedWindow;
687      private ActionMap actionMap;
688      /** @since 1.3 */
689      private boolean verifyInputWhenFocusTarget = true;
690      private InputVerifier inputVerifier;
691    
692      private TransferHandler transferHandler;
693    
694      /**
695       * Indicates if this component is currently painting a tile or not.
696       */
697      private boolean paintingTile;
698    
699      /**
700       * A temporary buffer used for fast dragging of components.
701       */
702      private Image dragBuffer;
703    
704      /**
705       * Indicates if the dragBuffer is already initialized.
706       */
707      private boolean dragBufferInitialized;
708    
709      /**
710       * A cached Rectangle object to be reused. Be careful when you use that,
711       * so that it doesn't get modified in another context within the same
712       * method call chain.
713       */
714      private static transient Rectangle rectCache;
715    
716      /**
717       * The default locale of the component.
718       * 
719       * @see #getDefaultLocale
720       * @see #setDefaultLocale
721       */
722      private static Locale defaultLocale;
723      
724      public static final String TOOL_TIP_TEXT_KEY = "ToolTipText";
725    
726      /**
727       * Constant used to indicate that no condition has been assigned to a
728       * particular action.
729       *
730       * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
731       */
732      public static final int UNDEFINED_CONDITION = -1;
733    
734      /**
735       * Constant used to indicate that an action should be performed only when 
736       * the component has focus.
737       *
738       * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
739       */
740      public static final int WHEN_FOCUSED = 0;
741    
742      /**
743       * Constant used to indicate that an action should be performed only when 
744       * the component is an ancestor of the component which has focus.
745       *
746       * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
747       */
748      public static final int WHEN_ANCESTOR_OF_FOCUSED_COMPONENT = 1;
749    
750      /**
751       * Constant used to indicate that an action should be performed only when 
752       * the component is in the window which has focus.
753       *
754       * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
755       */
756      public static final int WHEN_IN_FOCUSED_WINDOW = 2;
757    
758    
759      /**
760       * Used to optimize painting. This is set in paintImmediately2() to specify
761       * the exact component path to be painted by paintChildren.
762       */
763      Component paintChild;
764    
765      /**
766       * Indicates if the opaque property has been set by a client program or by
767       * the UI.
768       *
769       * @see #setUIProperty(String, Object)
770       * @see LookAndFeel#installProperty(JComponent, String, Object)
771       */
772      private boolean clientOpaqueSet = false;
773    
774      /**
775       * Indicates if the autoscrolls property has been set by a client program or
776       * by the UI.
777       *
778       * @see #setUIProperty(String, Object)
779       * @see LookAndFeel#installProperty(JComponent, String, Object)
780       */
781      private boolean clientAutoscrollsSet = false;
782    
783      /**
784       * Creates a new <code>JComponent</code> instance.
785       */
786      public JComponent()
787      {
788        super();
789        setDropTarget(new DropTarget());
790        setLocale(getDefaultLocale());
791        debugGraphicsOptions = DebugGraphics.NONE_OPTION;
792        setRequestFocusEnabled(true);
793      }
794    
795      /**
796       * Helper to lazily construct and return the client properties table.
797       * 
798       * @return The current client properties table
799       *
800       * @see #clientProperties
801       * @see #getClientProperty
802       * @see #putClientProperty
803       */
804      private Hashtable getClientProperties()
805      {
806        if (clientProperties == null)
807          clientProperties = new Hashtable();
808        return clientProperties;
809      }
810    
811      /**
812       * Get a client property associated with this component and a particular
813       * key.
814       *
815       * @param key The key with which to look up the client property
816       *
817       * @return A client property associated with this object and key
818       *
819       * @see #clientProperties
820       * @see #getClientProperties
821       * @see #putClientProperty
822       */
823      public final Object getClientProperty(Object key)
824      {
825        return getClientProperties().get(key);
826      }
827    
828      /**
829       * Add a client property <code>value</code> to this component, associated
830       * with <code>key</code>. If there is an existing client property
831       * associated with <code>key</code>, it will be replaced.  A
832       * {@link PropertyChangeEvent} is sent to registered listeners (with the
833       * name of the property being <code>key.toString()</code>).
834       *
835       * @param key The key of the client property association to add
836       * @param value The value of the client property association to add
837       *
838       * @see #clientProperties
839       * @see #getClientProperties
840       * @see #getClientProperty
841       */
842      public final void putClientProperty(Object key, Object value)
843      {
844        Hashtable t = getClientProperties();
845        Object old = t.get(key);
846        if (value != null)
847          t.put(key, value);
848        else
849          t.remove(key);
850    
851        // When both old and new value are null, no event is fired. This is
852        // different from what firePropertyChange() normally does, so we add this
853        // check here.
854        if (old != null || value != null)
855          firePropertyChange(key.toString(), old, value);
856      }
857    
858      /**
859       * Unregister an <code>AncestorListener</code>.
860       *
861       * @param listener The listener to unregister
862       * 
863       * @see #addAncestorListener
864       */
865      public void removeAncestorListener(AncestorListener listener)
866      {
867        listenerList.remove(AncestorListener.class, listener);
868      }
869    
870      /**
871       * Unregister a <code>VetoableChangeChangeListener</code>.
872       *
873       * @param listener The listener to unregister
874       *
875       * @see #addVetoableChangeListener
876       */
877      public void removeVetoableChangeListener(VetoableChangeListener listener)
878      {
879        if (vetoableChangeSupport != null)
880          vetoableChangeSupport.removeVetoableChangeListener(listener);
881      }
882    
883      /**
884       * Register an <code>AncestorListener</code>.
885       *
886       * @param listener The listener to register
887       *
888       * @see #removeVetoableChangeListener
889       */
890      public void addAncestorListener(AncestorListener listener)
891      {
892        listenerList.add(AncestorListener.class, listener);
893      }
894    
895      /**
896       * Register a <code>VetoableChangeListener</code>.
897       *
898       * @param listener The listener to register
899       *
900       * @see #removeVetoableChangeListener
901       * @see #listenerList
902       */
903      public void addVetoableChangeListener(VetoableChangeListener listener)
904      {
905        // Lazily instantiate this, it's rarely needed.
906        if (vetoableChangeSupport == null)
907          vetoableChangeSupport = new VetoableChangeSupport(this);
908        vetoableChangeSupport.addVetoableChangeListener(listener);
909      }
910    
911      /**
912       * Returns all registered {@link EventListener}s of the given 
913       * <code>listenerType</code>.
914       *
915       * @param listenerType the class of listeners to filter (<code>null</code> 
916       *                     not permitted).
917       *                     
918       * @return An array of registered listeners.
919       * 
920       * @throws ClassCastException if <code>listenerType</code> does not implement
921       *                            the {@link EventListener} interface.
922       * @throws NullPointerException if <code>listenerType</code> is 
923       *                              <code>null</code>.
924       *                            
925       * @see #getAncestorListeners()
926       * @see #listenerList
927       * 
928       * @since 1.3
929       */
930      public <T extends EventListener> T[] getListeners(Class<T> listenerType)
931      {
932        if (listenerType == PropertyChangeListener.class)
933          return (T[]) getPropertyChangeListeners();
934        else if (listenerType == VetoableChangeListener.class)
935          return (T[]) getVetoableChangeListeners();
936        else
937          return listenerList.getListeners(listenerType);
938      }
939    
940      /**
941       * Return all registered <code>AncestorListener</code> objects.
942       *
943       * @return The set of <code>AncestorListener</code> objects in {@link
944       * #listenerList}
945       */
946      public AncestorListener[] getAncestorListeners()
947      {
948        return (AncestorListener[]) getListeners(AncestorListener.class);
949      }
950    
951      /**
952       * Return all registered <code>VetoableChangeListener</code> objects.
953       *
954       * @return An array of the <code>VetoableChangeListener</code> objects 
955       *     registered with this component (possibly empty but never 
956       *     <code>null</code>).
957       * 
958       * @since 1.4
959       */
960      public VetoableChangeListener[] getVetoableChangeListeners()
961      {    
962        return vetoableChangeSupport == null ? new VetoableChangeListener[0]
963            : vetoableChangeSupport.getVetoableChangeListeners();
964      }
965    
966      /**
967       * Call {@link VetoableChangeListener#vetoableChange} on all listeners
968       * registered to listen to a given property. Any method which changes
969       * the specified property of this component should call this method.
970       *
971       * @param propertyName The property which changed
972       * @param oldValue The old value of the property
973       * @param newValue The new value of the property
974       *
975       * @throws PropertyVetoException if the change was vetoed by a listener
976       *
977       * @see #addVetoableChangeListener
978       * @see #removeVetoableChangeListener
979       */
980      protected void fireVetoableChange(String propertyName, Object oldValue,
981                                        Object newValue)
982        throws PropertyVetoException
983      {
984        if (vetoableChangeSupport != null)
985          vetoableChangeSupport.fireVetoableChange(propertyName, oldValue, newValue);
986      }
987    
988    
989      /**
990       * Fires a property change for a primitive integer property.
991       *
992       * @param property the name of the property
993       * @param oldValue the old value of the property
994       * @param newValue the new value of the property
995       *
996       * @specnote This method is implemented in
997       *           {@link Component#firePropertyChange(String, int, int)}. It is
998       *           only here because it is specified to be public, whereas the
999       *           Component method is protected.
1000       */
1001      public void firePropertyChange(String property, int oldValue, int newValue)
1002      {
1003        super.firePropertyChange(property, oldValue, newValue);
1004      }
1005      
1006      /**
1007       * Fires a property change for a primitive boolean property.
1008       *
1009       * @param property the name of the property
1010       * @param oldValue the old value of the property
1011       * @param newValue the new value of the property
1012       *
1013       * @specnote This method is implemented in
1014       *           {@link Component#firePropertyChange(String, boolean, boolean)}.
1015       *           It is only here because it is specified to be public, whereas
1016       *           the Component method is protected.
1017       */
1018      public void firePropertyChange(String property, boolean oldValue,
1019                                     boolean newValue)
1020      {
1021        super.firePropertyChange(property, oldValue, newValue);
1022      }
1023    
1024      /**
1025       * Get the value of the accessibleContext property for this component.
1026       *
1027       * @return the current value of the property
1028       */
1029      public AccessibleContext getAccessibleContext()
1030      {
1031        return null;
1032      }
1033    
1034      /**
1035       * Get the value of the {@link #alignmentX} property.
1036       *
1037       * @return The current value of the property.
1038       *
1039       * @see #setAlignmentX
1040       * @see #alignmentY
1041       */
1042      public float getAlignmentX()
1043      {
1044        float ret = alignmentX;
1045        if (alignmentX < 0)
1046          // alignment has not been set explicitly.
1047          ret = super.getAlignmentX();
1048    
1049        return ret;
1050      }
1051    
1052      /**
1053       * Get the value of the {@link #alignmentY} property.
1054       *
1055       * @return The current value of the property.
1056       *
1057       * @see #setAlignmentY
1058       * @see #alignmentX
1059       */
1060      public float getAlignmentY()
1061      {
1062        float ret = alignmentY;
1063        if (alignmentY < 0)
1064          // alignment has not been set explicitly.
1065          ret = super.getAlignmentY();
1066    
1067        return ret;
1068      }
1069    
1070      /**
1071       * Get the current value of the {@link #autoscrolls} property.
1072       *
1073       * @return The current value of the property
1074       */
1075      public boolean getAutoscrolls()
1076      {
1077        return autoscrolls;
1078      }
1079    
1080      /**
1081       * Set the value of the {@link #border} property.
1082       *   
1083       * @param newBorder The new value of the property
1084       *
1085       * @see #getBorder
1086       */
1087      public void setBorder(Border newBorder)
1088      {
1089        Border oldBorder = getBorder();
1090        if (oldBorder == newBorder)
1091          return;
1092    
1093        border = newBorder;
1094        firePropertyChange("border", oldBorder, newBorder);
1095        repaint();
1096      }
1097    
1098      /**
1099       * Get the value of the {@link #border} property.
1100       *
1101       * @return The property's current value
1102       *
1103       * @see #setBorder
1104       */
1105      public Border getBorder()
1106      {
1107        return border;
1108      }
1109    
1110      /**
1111       * Get the component's current bounding box. If a rectangle is provided,
1112       * use this as the return value (adjusting its fields in place);
1113       * otherwise (of <code>null</code> is provided) return a new {@link
1114       * Rectangle}.
1115       *
1116       * @param rv Optional return value to use
1117       *
1118       * @return A rectangle bounding the component
1119       */
1120      public Rectangle getBounds(Rectangle rv)
1121      {
1122        if (rv == null)
1123          return new Rectangle(getX(), getY(), getWidth(), getHeight());
1124        else
1125          {
1126            rv.setBounds(getX(), getY(), getWidth(), getHeight());
1127            return rv;
1128          }
1129      }
1130    
1131      /**
1132       * Prepares a graphics context for painting this object. If {@link
1133       * #debugGraphicsOptions} is not equal to {@link
1134       * DebugGraphics#NONE_OPTION}, produce a new {@link DebugGraphics} object
1135       * wrapping the parameter. Otherwise configure the parameter with this
1136       * component's foreground color and font.
1137       *
1138       * @param g The graphics context to wrap or configure
1139       *
1140       * @return A graphics context to paint this object with
1141       *
1142       * @see #debugGraphicsOptions
1143       * @see #paint
1144       */
1145      protected Graphics getComponentGraphics(Graphics g)
1146      {
1147        Graphics g2 = g;
1148        int options = getDebugGraphicsOptions();
1149        if (options != DebugGraphics.NONE_OPTION)
1150          {
1151            if (!(g2 instanceof DebugGraphics))
1152              g2 = new DebugGraphics(g);
1153            DebugGraphics dg = (DebugGraphics) g2;
1154            dg.setDebugOptions(dg.getDebugOptions() | options);
1155          }
1156        g2.setFont(this.getFont());
1157        g2.setColor(this.getForeground());
1158        return g2;
1159      }
1160    
1161      /**
1162       * Get the value of the {@link #debugGraphicsOptions} property.
1163       *
1164       * @return The current value of the property.
1165       *
1166       * @see #setDebugGraphicsOptions
1167       * @see #debugGraphicsOptions
1168       */
1169      public int getDebugGraphicsOptions()
1170      {
1171        String option = System.getProperty("gnu.javax.swing.DebugGraphics");
1172        int options = debugGraphicsOptions;
1173        if (option != null && option.length() != 0)
1174          {
1175            if (options < 0)
1176              options = 0;
1177    
1178            if (option.equals("LOG"))
1179              options |= DebugGraphics.LOG_OPTION;
1180            else if (option.equals("FLASH"))
1181              options |= DebugGraphics.FLASH_OPTION;
1182          }
1183        return options;
1184      }
1185    
1186      /**
1187       * Get the component's insets, which are calculated from
1188       * the {@link #border} property. If the border is <code>null</code>,
1189       * calls {@link Container#getInsets}.
1190       *
1191       * @return The component's current insets
1192       */
1193      public Insets getInsets()
1194      {
1195        if (border == null)
1196          return super.getInsets();
1197        return getBorder().getBorderInsets(this);
1198      }
1199    
1200      /**
1201       * Get the component's insets, which are calculated from the {@link
1202       * #border} property. If the border is <code>null</code>, calls {@link
1203       * Container#getInsets}. The passed-in {@link Insets} value will be
1204       * used as the return value, if possible.
1205       *
1206       * @param insets Return value object to reuse, if possible
1207       *
1208       * @return The component's current insets
1209       */
1210      public Insets getInsets(Insets insets)
1211      {
1212        Insets t = getInsets();
1213    
1214        if (insets == null)
1215          return t;
1216    
1217        insets.left = t.left;
1218        insets.right = t.right;
1219        insets.top = t.top;
1220        insets.bottom = t.bottom;
1221        return insets;
1222      }
1223    
1224      /**
1225       * Get the component's location. The passed-in {@link Point} value
1226       * will be used as the return value, if possible.
1227       *
1228       * @param rv Return value object to reuse, if possible
1229       *
1230       * @return The component's current location
1231       */
1232      public Point getLocation(Point rv)
1233      {
1234        if (rv == null)
1235          return new Point(getX(), getY());
1236    
1237        rv.setLocation(getX(), getY());
1238        return rv;
1239      }
1240    
1241      /**
1242       * Get the component's maximum size. If the <code>maximumSize</code> property
1243       * has been explicitly set, it is returned. If the <code>maximumSize</code>
1244       * property has not been set but the {@link #ui} property has been, the
1245       * result of {@link ComponentUI#getMaximumSize} is returned. If neither
1246       * property has been set, the result of {@link Container#getMaximumSize}
1247       * is returned.
1248       *
1249       * @return the maximum size of the component
1250       *
1251       * @see Component#setMaximumSize
1252       * @see Component#getMaximumSize()
1253       * @see Component#isMaximumSizeSet()
1254       * @see ComponentUI#getMaximumSize(JComponent)
1255       */
1256      public Dimension getMaximumSize()
1257      {
1258        Dimension size = null; 
1259        if (isMaximumSizeSet())
1260          size = super.getMaximumSize();
1261        else
1262          {
1263            if (ui != null)
1264              size = ui.getMaximumSize(this);
1265            if (size == null)
1266              size = super.getMaximumSize();
1267          }
1268        return size;
1269      }
1270    
1271      /**
1272       * Get the component's minimum size. If the <code>minimumSize</code> property
1273       * has been explicitly set, it is returned. If the <code>minimumSize</code>
1274       * property has not been set but the {@link #ui} property has been, the
1275       * result of {@link ComponentUI#getMinimumSize} is returned. If neither
1276       * property has been set, the result of {@link Container#getMinimumSize}
1277       * is returned.
1278       *
1279       * @return The minimum size of the component
1280       *
1281       * @see Component#setMinimumSize
1282       * @see Component#getMinimumSize()
1283       * @see Component#isMinimumSizeSet()
1284       * @see ComponentUI#getMinimumSize(JComponent)
1285       */
1286      public Dimension getMinimumSize()
1287      {
1288        Dimension size = null; 
1289        if (isMinimumSizeSet())
1290          size = super.getMinimumSize();
1291        else
1292          {
1293            if (ui != null)
1294              size = ui.getMinimumSize(this);
1295            if (size == null)
1296              size = super.getMinimumSize();
1297          }
1298        return size;
1299      }
1300    
1301      /**
1302       * Get the component's preferred size. If the <code>preferredSize</code>
1303       * property has been explicitly set, it is returned. If the
1304       * <code>preferredSize</code> property has not been set but the {@link #ui}
1305       * property has been, the result of {@link ComponentUI#getPreferredSize} is
1306       * returned. If neither property has been set, the result of {@link
1307       * Container#getPreferredSize} is returned.
1308       *
1309       * @return The preferred size of the component
1310       *
1311       * @see Component#setPreferredSize
1312       * @see Component#getPreferredSize()
1313       * @see Component#isPreferredSizeSet()
1314       * @see ComponentUI#getPreferredSize(JComponent)
1315       */
1316      public Dimension getPreferredSize()
1317      {
1318        Dimension size = null; 
1319        if (isPreferredSizeSet())
1320          size = super.getPreferredSize();
1321        else
1322          {
1323            if (ui != null)
1324              size = ui.getPreferredSize(this);
1325            if (size == null)
1326              size = super.getPreferredSize();
1327          }
1328        return size;
1329      }
1330    
1331      /**
1332       * Return the value of the <code>nextFocusableComponent</code> property.
1333       *
1334       * @return The current value of the property, or <code>null</code>
1335       * if none has been set.
1336       * 
1337       * @deprecated See {@link java.awt.FocusTraversalPolicy}
1338       */
1339      public Component getNextFocusableComponent()
1340      {
1341        Container focusRoot = this;
1342        if (! this.isFocusCycleRoot())
1343          focusRoot = getFocusCycleRootAncestor();
1344    
1345        FocusTraversalPolicy policy  = focusRoot.getFocusTraversalPolicy();
1346        return policy.getComponentAfter(focusRoot, this);
1347      }
1348    
1349      /**
1350       * Return the set of {@link KeyStroke} objects which are registered
1351       * to initiate actions on this component.
1352       *
1353       * @return An array of the registered keystrokes (possibly empty but never
1354       *     <code>null</code>).
1355       */
1356      public KeyStroke[] getRegisteredKeyStrokes()
1357      {
1358        KeyStroke[] ks0;
1359        KeyStroke[] ks1;
1360        KeyStroke[] ks2;
1361        if (inputMap_whenFocused != null)
1362          ks0 = inputMap_whenFocused.keys();
1363        else 
1364          ks0 = new KeyStroke[0];
1365        if (inputMap_whenAncestorOfFocused != null)
1366          ks1 = inputMap_whenAncestorOfFocused.keys();
1367        else 
1368          ks1 = new KeyStroke[0];
1369        if (inputMap_whenInFocusedWindow != null)
1370          ks2 = inputMap_whenInFocusedWindow.keys();
1371        else
1372          ks2 = new KeyStroke[0];
1373        int count = ks0.length + ks1.length + ks2.length;
1374        KeyStroke[] result = new KeyStroke[count];
1375        System.arraycopy(ks0, 0, result, 0, ks0.length);
1376        System.arraycopy(ks1, 0, result, ks0.length, ks1.length);
1377        System.arraycopy(ks2, 0, result, ks0.length + ks1.length, ks2.length);
1378        return result;
1379      }
1380    
1381      /**
1382       * Returns the first ancestor of this component which is a {@link JRootPane}.
1383       * Equivalent to calling <code>SwingUtilities.getRootPane(this);</code>.
1384       *
1385       * @return An ancestral JRootPane, or <code>null</code> if none exists.
1386       */
1387      public JRootPane getRootPane()
1388      {
1389        JRootPane p = SwingUtilities.getRootPane(this);
1390        return p;
1391      }
1392    
1393      /**
1394       * Get the component's size. The passed-in {@link Dimension} value
1395       * will be used as the return value, if possible.
1396       *
1397       * @param rv Return value object to reuse, if possible
1398       *
1399       * @return The component's current size
1400       */
1401      public Dimension getSize(Dimension rv)
1402      {
1403        if (rv == null)
1404          return new Dimension(getWidth(), getHeight());
1405        else
1406          {
1407            rv.setSize(getWidth(), getHeight());
1408            return rv;
1409          }
1410      }
1411    
1412      /**
1413       * Return the <code>toolTip</code> property of this component, creating it and
1414       * setting it if it is currently <code>null</code>. This method can be
1415       * overridden in subclasses which wish to control the exact form of
1416       * tooltip created.
1417       *
1418       * @return The current toolTip
1419       */
1420      public JToolTip createToolTip()
1421      {
1422        JToolTip toolTip = new JToolTip();
1423        toolTip.setComponent(this);
1424        return toolTip;
1425      }
1426    
1427      /**
1428       * Return the location at which the <code>toolTipText</code> property should
1429       * be displayed, when triggered by a particular mouse event. 
1430       *
1431       * @param event The event the tooltip is being presented in response to
1432       *
1433       * @return The point at which to display a tooltip, or <code>null</code>
1434       *     if swing is to choose a default location.
1435       */
1436      public Point getToolTipLocation(MouseEvent event)
1437      {
1438        return null;
1439      }
1440    
1441      /**
1442       * Set the tooltip text for this component. If a non-<code>null</code>
1443       * value is set, this component is registered in the
1444       * <code>ToolTipManager</code> in order to turn on tooltips for this
1445       * component. If a <code>null</code> value is set, tooltips are turne off
1446       * for this component.
1447       *
1448       * @param text the tooltip text for this component
1449       *
1450       * @see #getToolTipText()
1451       * @see #getToolTipText(MouseEvent)
1452       */
1453      public void setToolTipText(String text)
1454      {
1455        String old = getToolTipText();
1456        putClientProperty(TOOL_TIP_TEXT_KEY, text);
1457        ToolTipManager ttm = ToolTipManager.sharedInstance();
1458        if (text == null)
1459          ttm.unregisterComponent(this);
1460        else if (old == null)
1461          ttm.registerComponent(this);
1462      }
1463    
1464      /**
1465       * Returns the current tooltip text for this component, or <code>null</code>
1466       * if none has been set.
1467       *
1468       * @return the current tooltip text for this component, or <code>null</code>
1469       *         if none has been set
1470       *
1471       * @see #setToolTipText
1472       * @see #getToolTipText(MouseEvent)
1473       */
1474      public String getToolTipText()
1475      {
1476        return (String) getClientProperty(TOOL_TIP_TEXT_KEY);
1477      }
1478    
1479      /**
1480       * Returns the tooltip text for this component for a particular mouse
1481       * event. This can be used to support context sensitive tooltips that can
1482       * change with the mouse location. By default this returns the static
1483       * tooltip text returned by {@link #getToolTipText()}.
1484       *
1485       * @param event the mouse event which triggered the tooltip
1486       *
1487       * @return the tooltip text for this component for a particular mouse
1488       *         event
1489       *
1490       * @see #setToolTipText
1491       * @see #getToolTipText()
1492       */
1493      public String getToolTipText(MouseEvent event)
1494      {
1495        return getToolTipText();
1496      }
1497      
1498      /**
1499       * Returns the flag that controls whether or not the component inherits its
1500       * parent's popup menu when no popup menu is specified for this component.
1501       * 
1502       * @return A boolean.
1503       * 
1504       * @since 1.5
1505       * 
1506       * @see #setInheritsPopupMenu(boolean)
1507       */
1508      public boolean getInheritsPopupMenu()
1509      {
1510        return inheritsPopupMenu; 
1511      }
1512      
1513      /**
1514       * Sets the flag that controls whether or not the component inherits its
1515       * parent's popup menu when no popup menu is specified for this component.
1516       * This is a bound property with the property name 'inheritsPopupMenu'.
1517       * 
1518       * @param inherit  the new flag value.
1519       * 
1520       * @since 1.5
1521       * 
1522       * @see #getInheritsPopupMenu()
1523       */
1524      public void setInheritsPopupMenu(boolean inherit)
1525      {
1526        if (inheritsPopupMenu != inherit)
1527          {
1528            inheritsPopupMenu = inherit;
1529            this.firePropertyChange("inheritsPopupMenu", ! inherit, inherit);
1530          }
1531      }
1532      
1533      /**
1534       * Returns the popup menu for this component.  If the popup menu is 
1535       * <code>null</code> AND the {@link #getInheritsPopupMenu()} method returns
1536       * <code>true</code>, this method will return the parent's popup menu (if it
1537       * has one).
1538       * 
1539       * @return The popup menu (possibly <code>null</code>.
1540       * 
1541       * @since 1.5
1542       * 
1543       * @see #setComponentPopupMenu(JPopupMenu)
1544       * @see #getInheritsPopupMenu()
1545       */
1546      public JPopupMenu getComponentPopupMenu()
1547      {
1548        if (componentPopupMenu == null && getInheritsPopupMenu())
1549          {
1550            Container parent = getParent(); 
1551            if (parent instanceof JComponent)
1552              return ((JComponent) parent).getComponentPopupMenu();
1553            else
1554              return null;
1555          }
1556        else
1557          return componentPopupMenu;
1558      }
1559    
1560      /**
1561       * Sets the popup menu for this component (this is a bound property with 
1562       * the property name 'componentPopupMenu').
1563       * 
1564       * @param popup  the popup menu (<code>null</code> permitted).
1565       *
1566       * @since 1.5
1567       * 
1568       * @see #getComponentPopupMenu()
1569       */
1570      public void setComponentPopupMenu(JPopupMenu popup)
1571      {
1572        if (componentPopupMenu != popup)
1573          {
1574            JPopupMenu old = componentPopupMenu;
1575            componentPopupMenu = popup;
1576            firePropertyChange("componentPopupMenu", old, popup);
1577          }
1578      }
1579      
1580      /**
1581       * Return the top level ancestral container (usually a {@link
1582       * java.awt.Window} or {@link java.applet.Applet}) which this component is
1583       * contained within, or <code>null</code> if no ancestors exist.
1584       *
1585       * @return The top level container, if it exists
1586       */
1587      public Container getTopLevelAncestor()
1588      {
1589        Container c = getParent();
1590        for (Container peek = c; peek != null; peek = peek.getParent())
1591          c = peek;
1592        return c;
1593      }
1594    
1595      /**
1596       * Compute the component's visible rectangle, which is defined
1597       * recursively as either the component's bounds, if it has no parent, or
1598       * the intersection of the component's bounds with the visible rectangle
1599       * of its parent.
1600       *
1601       * @param rect The return value slot to place the visible rectangle in
1602       */
1603      public void computeVisibleRect(Rectangle rect)
1604      {
1605        Component c = getParent();
1606        if (c != null && c instanceof JComponent)
1607          {
1608            ((JComponent) c).computeVisibleRect(rect);
1609            rect.translate(-getX(), -getY());
1610            rect = SwingUtilities.computeIntersection(0, 0, getWidth(),
1611                                                      getHeight(), rect);
1612          }
1613        else
1614          rect.setRect(0, 0, getWidth(), getHeight());
1615      }
1616    
1617      /**
1618       * Return the component's visible rectangle in a new {@link Rectangle},
1619       * rather than via a return slot.
1620       *
1621       * @return the component's visible rectangle
1622       *
1623       * @see #computeVisibleRect(Rectangle)
1624       */
1625      public Rectangle getVisibleRect()
1626      {
1627        Rectangle r = new Rectangle();
1628        computeVisibleRect(r);
1629        return r;
1630      }
1631    
1632      /**
1633       * <p>Requests that this component receive input focus, giving window
1634       * focus to the top level ancestor of this component. Only works on
1635       * displayable, focusable, visible components.</p>
1636       *
1637       * <p>This method should not be called by clients; it is intended for
1638       * focus implementations. Use {@link Component#requestFocus()} instead.</p>
1639       *
1640       * @see Component#requestFocus()
1641       */
1642      public void grabFocus()
1643      {
1644        requestFocus();
1645      }
1646    
1647      /**
1648       * Get the value of the {@link #doubleBuffered} property.
1649       *
1650       * @return The property's current value
1651       */
1652      public boolean isDoubleBuffered()
1653      {
1654        return doubleBuffered;
1655      }
1656    
1657      /**
1658       * Return <code>true</code> if the provided component has no native peer;
1659       * in other words, if it is a "lightweight component".
1660       *
1661       * @param c The component to test for lightweight-ness
1662       *
1663       * @return Whether or not the component is lightweight
1664       */
1665      public static boolean isLightweightComponent(Component c)
1666      {
1667        return c.getPeer() instanceof LightweightPeer;
1668      }
1669    
1670      /**
1671       * Return <code>true</code> if you wish this component to manage its own
1672       * focus. In particular: if you want this component to be sent
1673       * <code>TAB</code> and <code>SHIFT+TAB</code> key events, and to not
1674       * have its children considered as focus transfer targets. If
1675       * <code>true</code>, focus traversal around this component changes to
1676       * <code>CTRL+TAB</code> and <code>CTRL+SHIFT+TAB</code>.
1677       *
1678       * @return <code>true</code> if you want this component to manage its own
1679       *     focus, otherwise (by default) <code>false</code>
1680       *
1681       * @deprecated 1.4 Use {@link Component#setFocusTraversalKeys(int, Set)} and
1682       *     {@link Container#setFocusCycleRoot(boolean)} instead
1683       */
1684      public boolean isManagingFocus()
1685      {
1686        return false;
1687      }
1688    
1689      /**
1690       * Return the current value of the {@link #opaque} property. 
1691       *
1692       * @return The current property value
1693       */
1694      public boolean isOpaque()
1695      {
1696        return opaque;
1697      }
1698    
1699      /**
1700       * Return <code>true</code> if the component can guarantee that none of its
1701       * children will overlap in Z-order. This is a hint to the painting system.
1702       * The default is to return <code>true</code>, but some components such as
1703       * {@link JLayeredPane} should override this to return <code>false</code>.
1704       *
1705       * @return Whether the component tiles its children
1706       */
1707      public boolean isOptimizedDrawingEnabled()
1708      {
1709        return true;
1710      }
1711    
1712      /**
1713       * Return <code>true</code> if this component is currently painting a tile,
1714       * this means that paint() is called again on another child component. This
1715       * method returns <code>false</code> if this component does not paint a tile
1716       * or if the last tile is currently painted.
1717       *
1718       * @return whether the component is painting a tile
1719       */
1720      public boolean isPaintingTile()
1721      {
1722        return paintingTile;
1723      }
1724    
1725      /**
1726       * Get the value of the {@link #requestFocusEnabled} property.
1727       *
1728       * @return The current value of the property
1729       */
1730      public boolean isRequestFocusEnabled()
1731      {
1732        return requestFocusEnabled;
1733      }
1734    
1735      /**
1736       * Return <code>true</code> if this component is a validation root; this
1737       * will cause calls to {@link #invalidate()} in this component's children
1738       * to be "captured" at this component, and not propagate to its parents.
1739       * For most components this should return <code>false</code>, but some
1740       * components such as {@link JViewport} will want to return
1741       * <code>true</code>.
1742       *
1743       * @return Whether this component is a validation root
1744       */
1745      public boolean isValidateRoot()
1746      {
1747        return false;
1748      }
1749    
1750      /**
1751       * <p>Paint the component. This is a delicate process, and should only be
1752       * called from the repaint thread, under control of the {@link
1753       * RepaintManager}. Client code should usually call {@link #repaint()} to
1754       * trigger painting.</p>
1755       *
1756       * <p>The body of the <code>paint</code> call involves calling {@link
1757       * #paintComponent}, {@link #paintBorder}, and {@link #paintChildren} in
1758       * order. If you want to customize painting behavior, you should override
1759       * one of these methods rather than <code>paint</code>.</p>
1760       *
1761       * <p>For more details on the painting sequence, see <a
1762       * href="http://java.sun.com/products/jfc/tsc/articles/painting/index.html">
1763       * this article</a>.</p>
1764       *
1765       * @param g The graphics context to paint with
1766       *
1767       * @see #paintImmediately(Rectangle)
1768       */
1769      public void paint(Graphics g)
1770      {
1771        RepaintManager rm = RepaintManager.currentManager(this);
1772        // We do a little stunt act here to switch on double buffering if it's
1773        // not already on. If we are not already doublebuffered, then we jump
1774        // into the method paintDoubleBuffered, which turns on the double buffer
1775        // and then calls paint(g) again. In the second call we go into the else
1776        // branch of this if statement and actually paint things to the double
1777        // buffer. When this method completes, the call stack unwinds back to
1778        // paintDoubleBuffered, where the buffer contents is finally drawn to the
1779        // screen.
1780        if (!paintingDoubleBuffered && isDoubleBuffered()
1781            && rm.isDoubleBufferingEnabled())
1782          {
1783            Rectangle clip = g.getClipBounds();
1784            paintDoubleBuffered(clip.x, clip.y, clip.width, clip.height);
1785          }
1786        else
1787          {
1788            if (getClientProperty("bufferedDragging") != null
1789                && dragBuffer == null)
1790              {
1791                initializeDragBuffer();
1792              }
1793            else if (getClientProperty("bufferedDragging") == null
1794                && dragBuffer != null)
1795              {
1796                dragBuffer = null;
1797              }
1798    
1799            Rectangle clip = g.getClipBounds();
1800            int clipX, clipY, clipW, clipH;
1801            if (clip == null)
1802              {
1803                clipX = 0;
1804                clipY = 0;
1805                clipW = getWidth();
1806                clipH = getHeight();
1807              }
1808            else
1809              {
1810                clipX = clip.x;
1811                clipY = clip.y;
1812                clipW = clip.width;
1813                clipH = clip.height;
1814              }
1815            if (dragBuffer != null && dragBufferInitialized)
1816              {
1817                g.drawImage(dragBuffer, 0, 0, this);
1818              }
1819            else
1820              {
1821                Graphics g2 = getComponentGraphics(g);
1822                if (! isOccupiedByChild(clipX, clipY, clipW, clipH))
1823                  {
1824                    paintComponent(g2);
1825                    paintBorder(g2);
1826                  }
1827                paintChildren(g2);
1828              }
1829          }
1830      }
1831    
1832      /**
1833       * Determines if a region of this component is completely occupied by
1834       * an opaque child component, in which case we don't need to bother
1835       * painting this component at all.
1836       *
1837       * @param x the area, x coordinate
1838       * @param y the area, y coordinate
1839       * @param w the area, width
1840       * @param h the area, height
1841       *
1842       * @return <code>true</code> if the specified area is completely covered
1843       *         by a child component, <code>false</code> otherwise
1844       */
1845      private boolean isOccupiedByChild(int x, int y, int w, int h)
1846      {
1847        boolean occupied = false;
1848        int count = getComponentCount();
1849        for (int i = 0; i < count; i++)
1850          {
1851            Component child = getComponent(i);
1852            int cx = child.getX();
1853            int cy = child.getY();
1854            int cw = child.getWidth();
1855            int ch = child.getHeight();
1856            if (child.isVisible() && x >= cx && x + w <= cx + cw && y >= cy
1857                && y + h <= cy + ch)
1858              {
1859                occupied = child.isOpaque();
1860                break;
1861              }
1862          }
1863        return occupied;
1864      }
1865    
1866      /**
1867       * Initializes the drag buffer by creating a new image and painting this
1868       * component into it.
1869       */
1870      private void initializeDragBuffer()
1871      {
1872        dragBufferInitialized = false;
1873        // Allocate new dragBuffer if the current one is too small.
1874        if (dragBuffer == null || dragBuffer.getWidth(this) < getWidth()
1875            || dragBuffer.getHeight(this) < getHeight())
1876          {
1877            dragBuffer = createImage(getWidth(), getHeight());
1878          }
1879        Graphics g = dragBuffer.getGraphics();
1880        paint(g);
1881        g.dispose();
1882        dragBufferInitialized = true;
1883      }
1884    
1885      /**
1886       * Paint the component's border. This usually means calling {@link
1887       * Border#paintBorder} on the {@link #border} property, if it is
1888       * non-<code>null</code>. You may override this if you wish to customize
1889       * border painting behavior. The border is painted after the component's
1890       * body, but before the component's children.
1891       *
1892       * @param g The graphics context with which to paint the border
1893       *
1894       * @see #paint
1895       * @see #paintChildren
1896       * @see #paintComponent
1897       */
1898      protected void paintBorder(Graphics g)
1899      {
1900        if (getBorder() != null)
1901          getBorder().paintBorder(this, g, 0, 0, getWidth(), getHeight());
1902      }
1903    
1904      /**
1905       * Paint the component's children. This usually means calling {@link
1906       * Container#paint}, which recursively calls {@link #paint} on any of the
1907       * component's children, with appropriate changes to coordinate space and
1908       * clipping region. You may override this if you wish to customize
1909       * children painting behavior. The children are painted after the
1910       * component's body and border.
1911       *
1912       * @param g The graphics context with which to paint the children
1913       *
1914       * @see #paint
1915       * @see #paintBorder
1916       * @see #paintComponent
1917       */
1918      protected void paintChildren(Graphics g)
1919      {
1920        if (getComponentCount() > 0)
1921          {
1922            // Need to lock the tree to avoid problems with AWT and concurrency.
1923            synchronized (getTreeLock())
1924              {
1925                // Fast forward to the child to paint, if set by
1926                // paintImmediately2()
1927                int i = getComponentCount() - 1;
1928                if (paintChild != null && paintChild.isOpaque())
1929                  {
1930                    for (; i >= 0 && getComponent(i) != paintChild; i--)
1931                      ;
1932                  }
1933                for (; i >= 0; i--)
1934                  {
1935                    Component child = getComponent(i);
1936                    if (child != null && child.isLightweight()
1937                        && child.isVisible())
1938                      {
1939                        int cx = child.getX();
1940                        int cy = child.getY();
1941                        int cw = child.getWidth();
1942                        int ch = child.getHeight();
1943                        if (g.hitClip(cx, cy, cw, ch))
1944                          {
1945                            if ((! isOptimizedDrawingEnabled()) && i > 0)
1946                              {
1947                                // Check if the child is completely obscured.
1948                                Rectangle clip = g.getClipBounds(); // A copy.
1949                                SwingUtilities.computeIntersection(cx, cy, cw, ch,
1950                                                                   clip);
1951                                if (isCompletelyObscured(i, clip.x, clip.y,
1952                                                         clip.width, clip.height))
1953                                  continue; // Continues the for-loop.
1954                              }
1955                            Graphics cg = g.create(cx, cy, cw, ch);
1956                            cg.setColor(child.getForeground());
1957                            cg.setFont(child.getFont());
1958                            try
1959                              {
1960                                child.paint(cg);
1961                              }
1962                            finally
1963                              {
1964                                cg.dispose();
1965                              }
1966                          }
1967                      }
1968                  }
1969              }
1970          }
1971      }
1972    
1973      /**
1974       * Determines if a region of a child component is completely obscured by one
1975       * of its siblings.
1976       *
1977       * @param index the index of the child component
1978       * @param x the region to check, x coordinate
1979       * @param y the region to check, y coordinate
1980       * @param w the region to check, width
1981       * @param h the region to check, height
1982       *
1983       * @return <code>true</code> if the region is completely obscured by a
1984       *         sibling, <code>false</code> otherwise
1985       */
1986      private boolean isCompletelyObscured(int index, int x, int y, int w, int h)
1987      {
1988        boolean obscured = false;
1989        for (int i = index - 1; i >= 0 && obscured == false; i--)
1990          {
1991            Component sib = getComponent(i);
1992            if (sib.isVisible())
1993              {
1994                Rectangle sibRect = sib.getBounds(rectCache);
1995                if (sib.isOpaque() && x >= sibRect.x
1996                    && (x + w) <= (sibRect.x + sibRect.width)
1997                    && y >= sibRect.y
1998                    && (y + h) <= (sibRect.y + sibRect.height))
1999                  {
2000                    obscured = true;
2001                  }
2002              }
2003          }
2004        return obscured;
2005      }
2006    
2007      /**
2008       * Checks if a component/rectangle is partially obscured by one of its
2009       * siblings.
2010       * Note that this doesn't check for completely obscured, this is
2011       * done by isCompletelyObscured() and should probably also be checked.
2012       *
2013       * @param i the component index from which to start searching
2014       * @param x the x coordinate of the rectangle to check
2015       * @param y the y coordinate of the rectangle to check
2016       * @param w the width of the rectangle to check
2017       * @param h the height of the rectangle to check
2018       *
2019       * @return <code>true</code> if the rectangle is partially obscured
2020       */
2021      private boolean isPartiallyObscured(int i, int x, int y, int w, int h)
2022      {
2023        boolean obscured = false;
2024        for (int j = i - 1; j >= 0 && ! obscured; j--)
2025          {
2026            Component sibl = getComponent(j);
2027            if (sibl.isVisible())
2028              {
2029                Rectangle rect = sibl.getBounds(rectCache);
2030                if (!(x + w <= rect.x)
2031                      || (y + h <= rect.y)
2032                      || (x >= rect.x + rect.width)
2033                      || (y >= rect.y + rect.height))
2034                  obscured = true;
2035              }
2036          }
2037        return obscured;
2038      }
2039    
2040      /**
2041       * Paint the component's body. This usually means calling {@link
2042       * ComponentUI#update} on the {@link #ui} property of the component, if
2043       * it is non-<code>null</code>. You may override this if you wish to
2044       * customize the component's body-painting behavior. The component's body
2045       * is painted first, before the border and children.
2046       *
2047       * @param g The graphics context with which to paint the body
2048       *
2049       * @see #paint
2050       * @see #paintBorder
2051       * @see #paintChildren
2052       */
2053      protected void paintComponent(Graphics g)
2054      {
2055        if (ui != null)
2056          {
2057            Graphics g2 = g.create();
2058            try
2059              {
2060                ui.update(g2, this);
2061              }
2062            finally
2063              {
2064                g2.dispose();
2065              }
2066          }
2067      }
2068    
2069      /**
2070       * A variant of {@link #paintImmediately(Rectangle)} which takes
2071       * integer parameters.
2072       *
2073       * @param x The left x coordinate of the dirty region
2074       * @param y The top y coordinate of the dirty region
2075       * @param w The width of the dirty region
2076       * @param h The height of the dirty region
2077       */
2078      public void paintImmediately(int x, int y, int w, int h)
2079      {
2080        // Find opaque parent and call paintImmediately2() on it.
2081        if (isShowing())
2082          {
2083            Component c = this;
2084            Component p;
2085            while (c != null && ! c.isOpaque())
2086              {
2087                p = c.getParent();
2088                if (p != null)
2089                  {
2090                    x += c.getX();
2091                    y += c.getY();
2092                    c = p;
2093                  }
2094              }
2095            if (c instanceof JComponent)
2096              ((JComponent) c).paintImmediately2(x, y, w, h);
2097            else
2098              c.repaint(x, y, w, h);
2099          }
2100      }
2101    
2102      /**
2103       * Transform the provided dirty rectangle for this component into the
2104       * appropriate ancestral {@link JRootPane} and call {@link #paint} on
2105       * that root pane. This method is called from the {@link RepaintManager}
2106       * and should always be called within the painting thread.
2107       *
2108       * <p>This method will acquire a double buffer from the {@link
2109       * RepaintManager} if the component's {@link #doubleBuffered} property is
2110       * <code>true</code> and the <code>paint</code> call is the
2111       * <em>first</em> recursive <code>paint</code> call inside swing.</p>
2112       *
2113       * <p>The method will also modify the provided {@link Graphics} context
2114       * via the {@link #getComponentGraphics} method. If you want to customize
2115       * the graphics object used for painting, you should override that method
2116       * rather than <code>paint</code>.</p>
2117       *
2118       * @param r The dirty rectangle to paint
2119       */
2120      public void paintImmediately(Rectangle r)
2121      {
2122        paintImmediately(r.x, r.y, r.width, r.height);
2123      }
2124    
2125      /**
2126       * Performs the actual work of paintImmediatly on the repaint root.
2127       *
2128       * @param x the area to be repainted, X coordinate
2129       * @param y the area to be repainted, Y coordinate
2130       */
2131      void paintImmediately2(int x, int y, int w, int h)
2132      {
2133        // Optimization for components that are always painted on top.
2134        boolean onTop = onTop() && isOpaque();
2135    
2136        // Fetch the RepaintManager.
2137        RepaintManager rm = RepaintManager.currentManager(this);
2138    
2139        // The painting clip;
2140        int paintX = x;
2141        int paintY = y;
2142        int paintW = w;
2143        int paintH = h;
2144    
2145        // If we should paint buffered or not.
2146        boolean haveBuffer = false;
2147    
2148        // The component that is finally triggered for painting.
2149        JComponent paintRoot = this;
2150        
2151        // Stores the component and all its parents. This will be used to limit
2152        // the actually painted components in paintChildren by setting
2153        // the field paintChild.
2154        int pIndex = -1;
2155        int pCount = 0;
2156        ArrayList components = new ArrayList();
2157    
2158        // Offset to subtract from the paintRoot rectangle when painting.
2159        int offsX = 0;
2160        int offsY = 0;
2161    
2162        // The current component and its child.
2163        Component child;
2164        Container c;
2165    
2166        // Find appropriate paint root.
2167        for (c = this, child = null;
2168             c != null && ! (c instanceof Window) && ! (c instanceof Applet);
2169             child = c, c = c.getParent())
2170          {
2171            JComponent jc = c instanceof JComponent ? (JComponent) c : null;
2172            components.add(c);
2173            if (! onTop && jc != null  && ! jc.isOptimizedDrawingEnabled())
2174              {
2175                // Indicates whether we reset the paint root to be the current
2176                // component.
2177                boolean updatePaintRoot = false;
2178    
2179                // Check obscured state of the child.
2180                // Generally, we have 3 cases here:
2181                // 1. Not obscured. No need to paint from the parent.
2182                // 2. Partially obscured. Paint from the parent.
2183                // 3. Completely obscured. No need to paint anything.
2184                if (c != this)
2185                  {
2186                    if (jc.isPaintRoot())
2187                      updatePaintRoot = true;
2188                    else
2189                      {
2190                        int count = c.getComponentCount();
2191                        int i = 0;
2192                        for (; i < count && c.getComponent(i) != child; i++)
2193                          ;
2194    
2195                        if (jc.isCompletelyObscured(i, paintX, paintY, paintW,
2196                                                    paintH))
2197                          return; // No need to paint anything.
2198                        else if (jc.isPartiallyObscured(i, paintX, paintY, paintW,
2199                                                        paintH))
2200                          updatePaintRoot = true;
2201                          
2202                      }
2203                  }
2204                if (updatePaintRoot)
2205                  {
2206                    // Paint from parent.
2207                    paintRoot = jc;
2208                    pIndex = pCount;
2209                    offsX = 0;
2210                    offsY = 0;
2211                    haveBuffer = false;
2212                  }
2213              }
2214            pCount++;
2215            // Check if component is double buffered.
2216            if (rm.isDoubleBufferingEnabled() && jc != null
2217                && jc.isDoubleBuffered())
2218              {
2219                haveBuffer = true;
2220              }
2221    
2222            // Clip the paint region with the parent.
2223            if (! onTop)
2224              {
2225                paintX = Math.max(0, paintX);
2226                paintY = Math.max(0, paintY);
2227                paintW = Math.min(c.getWidth(), paintW + paintX) - paintX;
2228                paintH = Math.min(c.getHeight(), paintH + paintY) - paintY;
2229                int dx = c.getX();
2230                int dy = c.getY();
2231                paintX += dx;
2232                paintY += dy;
2233                offsX += dx;
2234                offsY += dy;
2235              }
2236          }
2237        if (c != null && c.getPeer() != null && paintW > 0 && paintH > 0)
2238          {
2239            isRepainting = true;
2240            paintX -= offsX;
2241            paintY -= offsY;
2242    
2243            // Set the painting path so that paintChildren paints only what we
2244            // want.
2245            if (paintRoot != this)
2246              {
2247                for (int i = pIndex; i > 0; i--)
2248                  {
2249                    Component paintParent = (Component) components.get(i);
2250                    if (paintParent instanceof JComponent)
2251                      ((JComponent) paintParent).paintChild =
2252                        (Component) components.get(i - 1);
2253                  }
2254              }
2255    
2256            // Actually trigger painting.
2257            if (haveBuffer)
2258              paintRoot.paintDoubleBuffered(paintX, paintY, paintW, paintH);
2259            else
2260              {
2261                Graphics g = paintRoot.getGraphics();
2262                try
2263                  {
2264                    g.setClip(paintX, paintY, paintW, paintH);
2265                    paintRoot.paint(g);
2266                  }
2267                finally
2268                  {
2269                    g.dispose();
2270                  }
2271              }
2272    
2273            // Reset the painting path.
2274            if (paintRoot != this)
2275              {
2276                for (int i = pIndex; i > 0; i--)
2277                  {
2278                    Component paintParent = (Component) components.get(i);
2279                    if (paintParent instanceof JComponent)
2280                      ((JComponent) paintParent).paintChild = null;
2281                  }
2282              }
2283    
2284            isRepainting = false;
2285          }
2286      }
2287    
2288      /**
2289       * Returns <code>true</code> if the component is guaranteed to be painted
2290       * on top of others. This returns false by default and is overridden by
2291       * components like JMenuItem, JPopupMenu and JToolTip to return true for
2292       * added efficiency.
2293       *
2294       * @return <code>true</code> if the component is guaranteed to be painted
2295       *         on top of others
2296       */
2297      boolean onTop()
2298      {
2299        return false;
2300      }
2301    
2302      /**
2303       * This returns true when a component needs to force itself as a paint
2304       * origin. This is used for example in JViewport to make sure that it
2305       * gets to update its backbuffer.
2306       *
2307       * @return true when a component needs to force itself as a paint
2308       *         origin
2309       */
2310      boolean isPaintRoot()
2311      {
2312        return false;
2313      }
2314    
2315      /**
2316       * Performs double buffered repainting.
2317       */
2318      private void paintDoubleBuffered(int x, int y, int w, int h)
2319      {
2320        RepaintManager rm = RepaintManager.currentManager(this);
2321    
2322        // Paint on the offscreen buffer.
2323        Component root = SwingUtilities.getRoot(this);
2324        Image buffer = rm.getVolatileOffscreenBuffer(this, root.getWidth(),
2325                                                     root.getHeight());
2326    
2327        // The volatile offscreen buffer may be null when that's not supported
2328        // by the AWT backend. Fall back to normal backbuffer in this case.
2329        if (buffer == null)
2330          buffer = rm.getOffscreenBuffer(this, root.getWidth(), root.getHeight());
2331    
2332        //Rectangle targetClip = SwingUtilities.convertRectangle(this, r, root);
2333        Graphics g2 = buffer.getGraphics();
2334        clipAndTranslateGraphics(root, this, g2);
2335        g2.clipRect(x, y, w, h);
2336        g2 = getComponentGraphics(g2);
2337        paintingDoubleBuffered = true;
2338        try
2339          {
2340            if (isRepainting) // Called from paintImmediately, go through paint().
2341              paint(g2);
2342            else // Called from paint() (AWT refresh), don't call it again.
2343              {
2344                paintComponent(g2);
2345                paintBorder(g2);
2346                paintChildren(g2);
2347              }
2348          }
2349        finally
2350          {
2351            paintingDoubleBuffered = false;
2352            g2.dispose();
2353          }
2354    
2355        // Paint the buffer contents on screen.
2356        rm.commitBuffer(this, x, y, w, h);
2357      }
2358    
2359      /**
2360       * Clips and translates the Graphics instance for painting on the double
2361       * buffer. This has to be done, so that it reflects the component clip of the
2362       * target component.
2363       *
2364       * @param root the root component (top-level container usually)
2365       * @param target the component to be painted
2366       * @param g the Graphics instance
2367       */
2368      private void clipAndTranslateGraphics(Component root, Component target,
2369                                            Graphics g)
2370      {
2371        Component parent = target;
2372        int deltaX = 0;
2373        int deltaY = 0;
2374        while (parent != root)
2375          {
2376            deltaX += parent.getX();
2377            deltaY += parent.getY();
2378            parent = parent.getParent();
2379          }
2380        g.translate(deltaX, deltaY);
2381        g.clipRect(0, 0, target.getWidth(), target.getHeight());
2382      }
2383    
2384      /**
2385       * Performs normal painting without double buffering.
2386       *
2387       * @param r the area that should be repainted
2388       */
2389      void paintSimple(Rectangle r)
2390      {
2391        Graphics g = getGraphics();
2392        Graphics g2 = getComponentGraphics(g);
2393        g2.setClip(r);
2394        paint(g2);
2395        g2.dispose();
2396        if (g != g2)
2397          g.dispose();
2398      }
2399    
2400      /**
2401       * Return a string representation for this component, for use in
2402       * debugging.
2403       *
2404       * @return A string describing this component.
2405       */
2406      protected String paramString()
2407      {
2408        StringBuffer sb = new StringBuffer();
2409        sb.append(super.paramString());
2410        sb.append(",alignmentX=").append(getAlignmentX());
2411        sb.append(",alignmentY=").append(getAlignmentY());
2412        sb.append(",border=");
2413        if (getBorder() != null)
2414          sb.append(getBorder());
2415        sb.append(",maximumSize=");
2416        if (getMaximumSize() != null)
2417          sb.append(getMaximumSize());
2418        sb.append(",minimumSize=");
2419        if (getMinimumSize() != null)
2420          sb.append(getMinimumSize());
2421        sb.append(",preferredSize=");
2422        if (getPreferredSize() != null)
2423          sb.append(getPreferredSize());
2424        return sb.toString();
2425      }
2426    
2427      /**
2428       * A variant of {@link
2429       * #registerKeyboardAction(ActionListener,String,KeyStroke,int)} which
2430       * provides <code>null</code> for the command name.
2431       * 
2432       * @param act  the action listener to notify when the keystroke occurs.
2433       * @param stroke  the key stroke.
2434       * @param cond  the condition (one of {@link #WHEN_FOCUSED}, 
2435       *     {@link #WHEN_IN_FOCUSED_WINDOW} and 
2436       *     {@link #WHEN_ANCESTOR_OF_FOCUSED_COMPONENT}).
2437       */
2438      public void registerKeyboardAction(ActionListener act,
2439                                         KeyStroke stroke, 
2440                                         int cond)
2441      {
2442        registerKeyboardAction(act, null, stroke, cond);
2443      }
2444    
2445      /* 
2446       * There is some charmingly undocumented behavior sun seems to be using
2447       * to simulate the old register/unregister keyboard binding API. It's not
2448       * clear to me why this matters, but we shall endeavour to follow suit.
2449       *
2450       * Two main thing seem to be happening when you do registerKeyboardAction():
2451       * 
2452       *  - no actionMap() entry gets created, just an entry in inputMap()
2453       *
2454       *  - the inputMap() entry is a proxy class which invokes the the
2455       *  binding's actionListener as a target, and which clobbers the command
2456       *  name sent in the ActionEvent, providing the binding command name
2457       *  instead.
2458       *
2459       * This much you can work out just by asking the input and action maps
2460       * what they contain after making bindings, and watching the event which
2461       * gets delivered to the recipient. Beyond that, it seems to be a
2462       * sun-private solution so I will only immitate it as much as it matters
2463       * to external observers.
2464       */
2465      private static class ActionListenerProxy
2466        extends AbstractAction
2467      {
2468        ActionListener target;
2469        String bindingCommandName;
2470    
2471        public ActionListenerProxy(ActionListener li, 
2472                                   String cmd)
2473        {
2474          target = li;
2475          bindingCommandName = cmd;
2476        }
2477    
2478        public void actionPerformed(ActionEvent e)
2479        {
2480          ActionEvent derivedEvent = new ActionEvent(e.getSource(),
2481                                                     e.getID(),
2482                                                     bindingCommandName,
2483                                                     e.getModifiers());
2484          target.actionPerformed(derivedEvent);
2485        }
2486      }
2487    
2488      
2489      /**
2490       * An obsolete method to register a keyboard action on this component.
2491       * You should use <code>getInputMap</code> and <code>getActionMap</code>
2492       * to fetch mapping tables from keystrokes to commands, and commands to
2493       * actions, respectively, and modify those mappings directly.
2494       *
2495       * @param act The action to be registered
2496       * @param cmd The command to deliver in the delivered {@link
2497       *     java.awt.event.ActionEvent}
2498       * @param stroke The keystroke to register on
2499       * @param cond One of the values {@link #UNDEFINED_CONDITION},
2500       *     {@link #WHEN_ANCESTOR_OF_FOCUSED_COMPONENT}, {@link #WHEN_FOCUSED}, or
2501       *     {@link #WHEN_IN_FOCUSED_WINDOW}, indicating the condition which must
2502       *     be met for the action to be fired
2503       *
2504       * @see #unregisterKeyboardAction
2505       * @see #getConditionForKeyStroke
2506       * @see #resetKeyboardActions
2507       */
2508      public void registerKeyboardAction(ActionListener act, 
2509                                         String cmd,
2510                                         KeyStroke stroke, 
2511                                         int cond)
2512      {
2513        ActionListenerProxy proxy = new ActionListenerProxy(act, cmd);
2514        getInputMap(cond).put(stroke, proxy);
2515        getActionMap().put(proxy, proxy);
2516      }
2517    
2518      /**
2519       * Sets the input map for the given condition.
2520       * 
2521       * @param condition  the condition (one of {@link #WHEN_FOCUSED}, 
2522       *     {@link #WHEN_IN_FOCUSED_WINDOW} and 
2523       *     {@link #WHEN_ANCESTOR_OF_FOCUSED_COMPONENT}).
2524       * @param map  the map.
2525       * 
2526       * @throws IllegalArgumentException if <code>condition</code> is not one of
2527       *     the specified values.
2528       */
2529      public final void setInputMap(int condition, InputMap map)
2530      {
2531        enableEvents(AWTEvent.KEY_EVENT_MASK);
2532        switch (condition)
2533          {
2534          case WHEN_FOCUSED:
2535            inputMap_whenFocused = map;
2536            break;
2537    
2538          case WHEN_ANCESTOR_OF_FOCUSED_COMPONENT:
2539            inputMap_whenAncestorOfFocused = map;
2540            break;
2541    
2542          case WHEN_IN_FOCUSED_WINDOW:
2543            if (map != null && !(map instanceof ComponentInputMap))
2544                throw new 
2545                  IllegalArgumentException("WHEN_IN_FOCUSED_WINDOW " + 
2546                                           "InputMap must be a ComponentInputMap");
2547            inputMap_whenInFocusedWindow = (ComponentInputMap)map;
2548            break;
2549            
2550          case UNDEFINED_CONDITION:
2551          default:
2552            throw new IllegalArgumentException();
2553          }
2554      }
2555    
2556      /**
2557       * Returns the input map associated with this component for the given
2558       * state/condition.
2559       * 
2560       * @param condition  the state (one of {@link #WHEN_FOCUSED}, 
2561       *     {@link #WHEN_ANCESTOR_OF_FOCUSED_COMPONENT} and 
2562       *     {@link #WHEN_IN_FOCUSED_WINDOW}).
2563       * 
2564       * @return The input map.
2565       * @throws IllegalArgumentException if <code>condition</code> is not one of 
2566       *             the specified values.
2567       * @since 1.3
2568       */
2569      public final InputMap getInputMap(int condition)
2570      {
2571        enableEvents(AWTEvent.KEY_EVENT_MASK);
2572        switch (condition)
2573          {
2574          case WHEN_FOCUSED:
2575            if (inputMap_whenFocused == null)
2576              inputMap_whenFocused = new InputMap();
2577            return inputMap_whenFocused;
2578    
2579          case WHEN_ANCESTOR_OF_FOCUSED_COMPONENT:
2580            if (inputMap_whenAncestorOfFocused == null)
2581              inputMap_whenAncestorOfFocused = new InputMap();
2582            return inputMap_whenAncestorOfFocused;
2583    
2584          case WHEN_IN_FOCUSED_WINDOW:
2585            if (inputMap_whenInFocusedWindow == null)
2586              inputMap_whenInFocusedWindow = new ComponentInputMap(this);
2587            return inputMap_whenInFocusedWindow;
2588    
2589          case UNDEFINED_CONDITION:
2590          default:
2591            throw new IllegalArgumentException("Invalid 'condition' argument: " 
2592                                               + condition);
2593          }
2594      }
2595    
2596      /**
2597       * Returns the input map associated with this component for the 
2598       * {@link #WHEN_FOCUSED} state.
2599       * 
2600       * @return The input map.
2601       * 
2602       * @since 1.3
2603       * @see #getInputMap(int)
2604       */
2605      public final InputMap getInputMap()
2606      {
2607        return getInputMap(WHEN_FOCUSED);
2608      }
2609    
2610      public final ActionMap getActionMap()
2611      {
2612        if (actionMap == null)
2613          actionMap = new ActionMap();
2614        return actionMap;
2615      }
2616    
2617      public final void setActionMap(ActionMap map)
2618      {
2619        actionMap = map;
2620      }
2621    
2622      /**
2623       * Return the condition that determines whether a registered action
2624       * occurs in response to the specified keystroke.
2625       *
2626       * As of 1.3 KeyStrokes can be registered with multiple simultaneous
2627       * conditions.
2628       *
2629       * @param ks The keystroke to return the condition of
2630       *
2631       * @return One of the values {@link #UNDEFINED_CONDITION}, {@link
2632       *     #WHEN_ANCESTOR_OF_FOCUSED_COMPONENT}, {@link #WHEN_FOCUSED}, or {@link
2633       *     #WHEN_IN_FOCUSED_WINDOW}
2634       *
2635       * @see #registerKeyboardAction(ActionListener, KeyStroke, int)   
2636       * @see #unregisterKeyboardAction   
2637       * @see #resetKeyboardActions
2638       */
2639      public int getConditionForKeyStroke(KeyStroke ks)
2640      {
2641        if (inputMap_whenFocused != null 
2642            && inputMap_whenFocused.get(ks) != null)
2643          return WHEN_FOCUSED;
2644        else if (inputMap_whenAncestorOfFocused != null 
2645                 && inputMap_whenAncestorOfFocused.get(ks) != null)
2646          return WHEN_ANCESTOR_OF_FOCUSED_COMPONENT;
2647        else if (inputMap_whenInFocusedWindow != null 
2648                 && inputMap_whenInFocusedWindow.get(ks) != null)
2649          return WHEN_IN_FOCUSED_WINDOW;
2650        else
2651          return UNDEFINED_CONDITION;
2652      }
2653    
2654      /**
2655       * Get the ActionListener (typically an {@link Action} object) which is
2656       * associated with a particular keystroke. 
2657       *
2658       * @param ks The keystroke to retrieve the action of
2659       *
2660       * @return The action associated with the specified keystroke
2661       */
2662      public ActionListener getActionForKeyStroke(KeyStroke ks)
2663      {
2664        Object key = getInputMap(JComponent.WHEN_FOCUSED).get(ks);
2665        if (key == null)
2666          key = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).get(ks);
2667        if (key == null)
2668          key = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).get(ks);
2669        if (key != null)
2670          {
2671            if (key instanceof ActionListenerProxy)
2672              return ((ActionListenerProxy) key).target;
2673            else
2674              return getActionMap().get(key);
2675          }
2676        return null;
2677      }
2678    
2679      /**
2680       * A hook for subclasses which want to customize event processing.
2681       */
2682      protected void processComponentKeyEvent(KeyEvent e)
2683      {
2684        // This method does nothing, it is meant to be overridden by subclasses.
2685      }
2686    
2687      /**
2688       * Override the default key dispatch system from Component to hook into
2689       * the swing {@link InputMap} / {@link ActionMap} system.
2690       *
2691       * See <a
2692       * href="http://java.sun.com/products/jfc/tsc/special_report/kestrel/keybindings.html">
2693       * this report</a> for more details, it's somewhat complex.
2694       */
2695      protected void processKeyEvent(KeyEvent e)
2696      {
2697        // let the AWT event processing send KeyEvents to registered listeners
2698        super.processKeyEvent(e);
2699        processComponentKeyEvent(e);
2700    
2701        if (e.isConsumed())
2702          return;
2703    
2704        // Input maps are checked in this order:
2705        // 1. The focused component's WHEN_FOCUSED map is checked.
2706        // 2. The focused component's WHEN_ANCESTOR_OF_FOCUSED_COMPONENT map.
2707        // 3. The WHEN_ANCESTOR_OF_FOCUSED_COMPONENT maps of the focused
2708        //    component's parent, then its parent's parent, and so on.
2709        //    Note: Input maps for disabled components are skipped.
2710        // 4. The WHEN_IN_FOCUSED_WINDOW maps of all the enabled components in
2711        //    the focused window are searched.
2712        
2713        KeyStroke keyStroke = KeyStroke.getKeyStrokeForEvent(e);
2714        boolean pressed = e.getID() == KeyEvent.KEY_PRESSED;
2715        
2716        if (processKeyBinding(keyStroke, e, WHEN_FOCUSED, pressed))
2717          {
2718            // This is step 1 from above comment.
2719            e.consume();
2720            return;
2721          }
2722        else if (processKeyBinding
2723                 (keyStroke, e, WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, pressed))
2724          {
2725            // This is step 2 from above comment.
2726            e.consume();
2727            return;
2728          }
2729        
2730        // This is step 3 from above comment.
2731        Container current = getParent();    
2732        while (current != null)
2733          { 
2734            // If current is a JComponent, see if it handles the event in its
2735            // WHEN_ANCESTOR_OF_FOCUSED_COMPONENT maps.
2736            if ((current instanceof JComponent) && 
2737                ((JComponent)current).processKeyBinding 
2738                (keyStroke, e,WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, pressed))
2739              {
2740                e.consume();
2741                return;
2742              }     
2743            
2744            // Stop when we've tried a top-level container and it didn't handle it
2745            if (current instanceof Window || current instanceof Applet)
2746              break;        
2747            
2748            // Move up the hierarchy
2749            current = current.getParent();
2750          }
2751        
2752        // Current being null means the JComponent does not currently have a
2753        // top-level ancestor, in which case we don't need to check 
2754        // WHEN_IN_FOCUSED_WINDOW bindings.
2755        if (current == null || e.isConsumed())
2756          return;
2757        
2758        // This is step 4 from above comment.  KeyboardManager maintains mappings
2759        // related to WHEN_IN_FOCUSED_WINDOW bindings so that we don't have to 
2760        // traverse the containment hierarchy each time.
2761        if (KeyboardManager.getManager().processKeyStroke(current, keyStroke, e))
2762          e.consume();
2763      }
2764    
2765      protected boolean processKeyBinding(KeyStroke ks,
2766                                          KeyEvent e,
2767                                          int condition,
2768                                          boolean pressed)
2769      {
2770        if (isEnabled())
2771          {
2772            Action act = null;
2773            Object cmd = null;
2774            InputMap map = getInputMap(condition);
2775            if (map != null)
2776              {
2777                cmd = map.get(ks);
2778                if (cmd != null)
2779                  {
2780                    if (cmd instanceof ActionListenerProxy)
2781                      act = (Action) cmd;
2782                    else 
2783                      act = getActionMap().get(cmd);
2784                  }
2785              }
2786            if (act != null && act.isEnabled())
2787              {
2788                // Need to synchronize here so we don't get in trouble with
2789                // our __command__ hack.
2790                synchronized (act)
2791                  {
2792                    // We add the command as value to the action, so that
2793                    // the action can later determine the command with which it
2794                    // was called. This is undocumented, but shouldn't affect
2795                    // compatibility. It allows us to use only one Action instance
2796                    // to do the work for all components of one type, instead of
2797                    // having loads of small Actions. This effectivly saves startup
2798                    // time of Swing.
2799                    act.putValue("__command__", cmd);
2800                    return SwingUtilities.notifyAction(act, ks, e, this,
2801                                                       e.getModifiers());
2802                  }
2803              }
2804          }
2805        return false;
2806      }
2807      
2808      /**
2809       * Remove a keyboard action registry.
2810       *
2811       * @param aKeyStroke The keystroke to unregister
2812       *
2813       * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
2814       * @see #getConditionForKeyStroke
2815       * @see #resetKeyboardActions
2816       */
2817      public void unregisterKeyboardAction(KeyStroke aKeyStroke)
2818      {
2819        ActionMap am = getActionMap();
2820        // This loops through the conditions WHEN_FOCUSED,
2821        // WHEN_ANCESTOR_OF_FOCUSED_COMPONENT and WHEN_IN_FOCUSED_WINDOW.
2822        for (int cond = 0; cond < 3; cond++)
2823          {
2824            InputMap im = getInputMap(cond);
2825            if (im != null)
2826              {
2827                Object action = im.get(aKeyStroke);
2828                if (action != null && am != null)
2829                  am.remove(action);
2830                im.remove(aKeyStroke);
2831              }
2832          }
2833      }
2834    
2835    
2836      /**
2837       * Reset all keyboard action registries.
2838       *
2839       * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
2840       * @see #unregisterKeyboardAction
2841       * @see #getConditionForKeyStroke
2842       */
2843      public void resetKeyboardActions()
2844      {
2845        if (inputMap_whenFocused != null)
2846          inputMap_whenFocused.clear();
2847        if (inputMap_whenAncestorOfFocused != null)
2848          inputMap_whenAncestorOfFocused.clear();
2849        if (inputMap_whenInFocusedWindow != null)
2850          inputMap_whenInFocusedWindow.clear();
2851        if (actionMap != null)
2852          actionMap.clear();
2853      }
2854    
2855      /**
2856       * Mark the described region of this component as dirty in the current
2857       * {@link RepaintManager}. This will queue an asynchronous repaint using
2858       * the system painting thread in the near future.
2859       *
2860       * @param tm ignored
2861       * @param x coordinate of the region to mark as dirty
2862       * @param y coordinate of the region to mark as dirty
2863       * @param width dimension of the region to mark as dirty
2864       * @param height dimension of the region to mark as dirty
2865       */
2866      public void repaint(long tm, int x, int y, int width, int height)
2867      {
2868         RepaintManager.currentManager(this).addDirtyRegion(this, x, y, width,
2869                                                            height);
2870      }
2871    
2872      /**
2873       * Mark the described region of this component as dirty in the current
2874       * {@link RepaintManager}. This will queue an asynchronous repaint using
2875       * the system painting thread in the near future.
2876       *
2877       * @param r The rectangle to mark as dirty
2878       */
2879      public void repaint(Rectangle r)
2880      {
2881        RepaintManager.currentManager(this).addDirtyRegion(this, r.x, r.y, r.width,
2882                                                           r.height);
2883      }
2884    
2885      /**
2886       * Request focus on the default component of this component's {@link
2887       * FocusTraversalPolicy}.
2888       *
2889       * @return The result of {@link #requestFocus()}
2890       *
2891       * @deprecated Use {@link #requestFocus()} on the default component provided
2892       *     from the {@link FocusTraversalPolicy} instead.
2893       */
2894      public boolean requestDefaultFocus()
2895      {
2896        return false;
2897      }
2898    
2899      /**
2900       * Queue a an invalidation and revalidation of this component, using 
2901       * {@link RepaintManager#addInvalidComponent}.
2902       */
2903      public void revalidate()
2904      {
2905        // As long as we don't have a parent we don't need to do any layout, since
2906        // this is done anyway as soon as we get connected to a parent.
2907        if (getParent() == null)
2908          return;
2909    
2910        if (! EventQueue.isDispatchThread())
2911          SwingUtilities.invokeLater(new Runnable()
2912            {
2913              public void run()
2914              {
2915                revalidate();
2916              }
2917            });
2918        else
2919          {
2920            invalidate();
2921            RepaintManager.currentManager(this).addInvalidComponent(this);
2922          }
2923      }
2924    
2925      /**
2926       * Calls <code>scrollRectToVisible</code> on the component's parent. 
2927       * Components which can service this call should override.
2928       *
2929       * @param r The rectangle to make visible
2930       */
2931      public void scrollRectToVisible(Rectangle r)
2932      {
2933        // Search nearest JComponent.
2934        int xOffs = getX();
2935        int yOffs = getY();
2936        Component p;
2937        for (p = getParent(); p != null && ! (p instanceof JComponent);
2938             p = p.getParent())
2939          {
2940            xOffs += p.getX();
2941            yOffs += p.getY();
2942          }
2943        if (p != null)
2944          {
2945            r.x += xOffs;
2946            r.y += yOffs;
2947            JComponent jParent = (JComponent) p;
2948            jParent.scrollRectToVisible(r);
2949            r.x -= xOffs;
2950            r.y -= yOffs;
2951          }
2952      }
2953    
2954      /**
2955       * Set the value of the {@link #alignmentX} property.
2956       *
2957       * @param a The new value of the property
2958       */
2959      public void setAlignmentX(float a)
2960      {
2961        if (a < 0.0F)
2962          alignmentX = 0.0F;
2963        else if (a > 1.0)
2964          alignmentX = 1.0F;
2965        else
2966          alignmentX = a;
2967      }
2968    
2969      /**
2970       * Set the value of the {@link #alignmentY} property.
2971       *
2972       * @param a The new value of the property
2973       */
2974      public void setAlignmentY(float a)
2975      {
2976        if (a < 0.0F)
2977          alignmentY = 0.0F;
2978        else if (a > 1.0)
2979          alignmentY = 1.0F;
2980        else
2981          alignmentY = a;
2982      }
2983    
2984      /**
2985       * Set the value of the {@link #autoscrolls} property.
2986       *
2987       * @param a The new value of the property
2988       */
2989      public void setAutoscrolls(boolean a)
2990      {
2991        autoscrolls = a;
2992        clientAutoscrollsSet = true;
2993      }
2994    
2995      /**
2996       * Set the value of the {@link #debugGraphicsOptions} property.
2997       *
2998       * @param debugOptions The new value of the property
2999       */
3000      public void setDebugGraphicsOptions(int debugOptions)
3001      {
3002        debugGraphicsOptions = debugOptions;
3003      }
3004    
3005      /**
3006       * Set the value of the {@link #doubleBuffered} property.
3007       *
3008       * @param db The new value of the property
3009       */
3010      public void setDoubleBuffered(boolean db)
3011      {
3012        doubleBuffered = db;
3013      }
3014    
3015      /**
3016       * Set the value of the <code>enabled</code> property.
3017       *
3018       * @param enable The new value of the property
3019       */
3020      public void setEnabled(boolean enable)
3021      {
3022        if (enable == isEnabled())
3023          return;
3024        super.setEnabled(enable);
3025        firePropertyChange("enabled", !enable, enable);
3026        repaint();
3027      }
3028    
3029      /**
3030       * Set the value of the <code>font</code> property.
3031       *
3032       * @param f The new value of the property
3033       */
3034      public void setFont(Font f)
3035      {
3036        if (f == getFont())
3037          return;
3038        super.setFont(f);
3039        revalidate();
3040        repaint();
3041      }
3042    
3043      /**
3044       * Set the value of the <code>background</code> property.
3045       *
3046       * @param bg The new value of the property
3047       */
3048      public void setBackground(Color bg)
3049      {
3050        if (bg == getBackground())
3051          return;
3052        super.setBackground(bg);
3053        repaint();
3054      }
3055    
3056      /**
3057       * Set the value of the <code>foreground</code> property.
3058       *
3059       * @param fg The new value of the property
3060       */
3061      public void setForeground(Color fg)
3062      {
3063        if (fg == getForeground())
3064          return;
3065        super.setForeground(fg);
3066        repaint();
3067      }
3068    
3069      /**
3070       * Set the specified component to be the next component in the 
3071       * focus cycle, overriding the {@link FocusTraversalPolicy} for
3072       * this component.
3073       *
3074       * @param aComponent The component to set as the next focusable
3075       *
3076       * @deprecated Use FocusTraversalPolicy instead
3077       */
3078      public void setNextFocusableComponent(Component aComponent)
3079      {
3080        Container focusRoot = this;
3081        if (! this.isFocusCycleRoot())
3082          focusRoot = getFocusCycleRootAncestor();
3083    
3084        FocusTraversalPolicy policy  = focusRoot.getFocusTraversalPolicy();
3085        if (policy instanceof CompatibilityFocusTraversalPolicy)
3086          {
3087            policy = new CompatibilityFocusTraversalPolicy(policy);
3088            focusRoot.setFocusTraversalPolicy(policy);
3089          }
3090        CompatibilityFocusTraversalPolicy p =
3091          (CompatibilityFocusTraversalPolicy) policy;
3092    
3093        Component old = getNextFocusableComponent();
3094        if (old != null)
3095          {
3096            p.removeNextFocusableComponent(this, old);
3097          }
3098    
3099        if (aComponent != null)
3100          {
3101            p.addNextFocusableComponent(this, aComponent);
3102          }
3103      }
3104    
3105      /**
3106       * Set the value of the {@link #requestFocusEnabled} property.
3107       *
3108       * @param e The new value of the property
3109       */
3110      public void setRequestFocusEnabled(boolean e)
3111      {
3112        requestFocusEnabled = e;
3113      }
3114    
3115      /**
3116       * Get the value of the {@link #transferHandler} property.
3117       *
3118       * @return The current value of the property
3119       *
3120       * @see #setTransferHandler
3121       */
3122    
3123      public TransferHandler getTransferHandler()
3124      {
3125        return transferHandler;
3126      }
3127    
3128      /**
3129       * Set the value of the {@link #transferHandler} property.
3130       *
3131       * @param newHandler The new value of the property
3132       *
3133       * @see #getTransferHandler
3134       */
3135    
3136      public void setTransferHandler(TransferHandler newHandler)
3137      {
3138        if (transferHandler == newHandler)
3139          return;
3140    
3141        TransferHandler oldHandler = transferHandler;
3142        transferHandler = newHandler;
3143        firePropertyChange("transferHandler", oldHandler, newHandler);
3144      }
3145    
3146      /**
3147       * Set if the component should paint all pixels withing its bounds.
3148       * If this property is set to false, the component expects the cleared
3149       * background.
3150       *
3151       * @param isOpaque if true, paint all pixels. If false, expect the clean
3152       * background. 
3153       *
3154       * @see ComponentUI#update
3155       */
3156      public void setOpaque(boolean isOpaque)
3157      {
3158        boolean oldOpaque = opaque;
3159        opaque = isOpaque;
3160        clientOpaqueSet = true;
3161        firePropertyChange("opaque", oldOpaque, opaque);
3162      }
3163    
3164      /**
3165       * Set the value of the visible property.
3166       *
3167       * If the value is changed, then the AncestorListeners of this component
3168       * and all its children (recursivly) are notified.
3169       *
3170       * @param v The new value of the property
3171       */
3172      public void setVisible(boolean v)
3173      {
3174        // No need to do anything if the actual value doesn't change.
3175        if (isVisible() == v)
3176          return;
3177    
3178        super.setVisible(v);
3179    
3180        // Notify AncestorListeners.
3181        if (v == true)
3182          fireAncestorEvent(this, AncestorEvent.ANCESTOR_ADDED);
3183        else
3184          fireAncestorEvent(this, AncestorEvent.ANCESTOR_REMOVED);
3185    
3186        Container parent = getParent();
3187        if (parent != null)
3188          parent.repaint(getX(), getY(), getWidth(), getHeight());
3189        revalidate();
3190      }
3191    
3192      /**
3193       * Call {@link #paint}. 
3194       * 
3195       * @param g The graphics context to paint into
3196       */
3197      public void update(Graphics g)
3198      {
3199        paint(g);
3200      }
3201    
3202      /**
3203       * Get the value of the UIClassID property. This property should be a key
3204       * in the {@link UIDefaults} table managed by {@link UIManager}, the
3205       * value of which is the name of a class to load for the component's
3206       * {@link #ui} property.
3207       *
3208       * @return A "symbolic" name which will map to a class to use for the
3209       * component's UI, such as <code>"ComponentUI"</code>
3210       *
3211       * @see #setUI
3212       * @see #updateUI
3213       */
3214      public String getUIClassID()
3215      {
3216        return "ComponentUI";
3217      }
3218    
3219      /**
3220       * Install a new UI delegate as the component's {@link #ui} property. In
3221       * the process, this will call {@link ComponentUI#uninstallUI} on any
3222       * existing value for the {@link #ui} property, and {@link
3223       * ComponentUI#installUI} on the new UI delegate.
3224       *
3225       * @param newUI The new UI delegate to install
3226       *
3227       * @see #updateUI
3228       * @see #getUIClassID
3229       */
3230      protected void setUI(ComponentUI newUI)
3231      {
3232        if (ui != null)
3233          ui.uninstallUI(this);
3234    
3235        ComponentUI oldUI = ui;
3236        ui = newUI;
3237    
3238        if (ui != null)
3239          ui.installUI(this);
3240    
3241        firePropertyChange("UI", oldUI, newUI);
3242        revalidate();
3243        repaint();
3244      }
3245    
3246      /**
3247       * This method should be overridden in subclasses. In JComponent, the
3248       * method does nothing. In subclasses, it should a UI delegate
3249       * (corresponding to the symbolic name returned from {@link
3250       * #getUIClassID}) from the {@link UIManager}, and calls {@link #setUI}
3251       * with the new delegate.
3252       */
3253      public void updateUI()
3254      {
3255        // Nothing to do here.
3256      }
3257    
3258      /**
3259       * Returns the locale used as the default for all new components.  The 
3260       * default value is {@link Locale#getDefault()} (that is, the platform
3261       * default locale).
3262       * 
3263       * @return The locale (never <code>null</code>).
3264       * 
3265       * @see #setDefaultLocale(Locale)
3266       */
3267      public static Locale getDefaultLocale()
3268      {
3269        if (defaultLocale == null)
3270          defaultLocale = Locale.getDefault();
3271        return defaultLocale;
3272      }
3273      
3274      /**
3275       * Sets the locale to be used as the default for all new components.  If this
3276       * is set to <code>null</code>, the {@link #getDefaultLocale()} method will
3277       * return the platform default locale.
3278       * 
3279       * @param l  the locale (<code>null</code> permitted).
3280       */
3281      public static void setDefaultLocale(Locale l)
3282      {
3283        defaultLocale = l;
3284      }
3285      
3286      /**
3287       * Returns the currently set input verifier for this component.
3288       *
3289       * @return the input verifier, or <code>null</code> if none
3290       */
3291      public InputVerifier getInputVerifier()
3292      {
3293        return inputVerifier;
3294      }
3295    
3296      /**
3297       * Sets the input verifier to use by this component.
3298       *
3299       * @param verifier the input verifier, or <code>null</code>
3300       */
3301      public void setInputVerifier(InputVerifier verifier)
3302      {
3303        InputVerifier oldVerifier = inputVerifier;
3304        inputVerifier = verifier;
3305        firePropertyChange("inputVerifier", oldVerifier, verifier);
3306      }
3307    
3308      /**
3309       * @since 1.3
3310       */
3311      public boolean getVerifyInputWhenFocusTarget()
3312      {
3313        return verifyInputWhenFocusTarget;
3314      }
3315    
3316      /**
3317       * @since 1.3
3318       */
3319      public void setVerifyInputWhenFocusTarget(boolean verifyInputWhenFocusTarget)
3320      {
3321        if (this.verifyInputWhenFocusTarget == verifyInputWhenFocusTarget)
3322          return;
3323    
3324        this.verifyInputWhenFocusTarget = verifyInputWhenFocusTarget;
3325        firePropertyChange("verifyInputWhenFocusTarget",
3326                           ! verifyInputWhenFocusTarget,
3327                           verifyInputWhenFocusTarget);
3328      }
3329    
3330      /**
3331       * Requests that this component gets the input focus if the
3332       * requestFocusEnabled property is set to <code>true</code>.
3333       * This also means that this component's top-level window becomes
3334       * the focused window, if that is not already the case.
3335       *
3336       * The preconditions that have to be met to become a focus owner is that
3337       * the component must be displayable, visible and focusable.
3338       *
3339       * Note that this signals only a request for becoming focused. There are
3340       * situations in which it is not possible to get the focus. So developers
3341       * should not assume that the component has the focus until it receives
3342       * a {@link java.awt.event.FocusEvent} with a value of
3343       * {@link java.awt.event.FocusEvent#FOCUS_GAINED}.
3344       *
3345       * @see Component#requestFocus()
3346       */
3347      public void requestFocus()
3348      {
3349        if (isRequestFocusEnabled())
3350          super.requestFocus();
3351      }
3352    
3353      /**
3354       * This method is overridden to make it public so that it can be used
3355       * by look and feel implementations.
3356       *
3357       * You should not use this method directly. Instead you are strongly
3358       * encouraged to call {@link #requestFocus()} or 
3359       * {@link #requestFocusInWindow()} instead.
3360       *
3361       * @param temporary if the focus change is temporary
3362       *
3363       * @return <code>false</code> if the focus change request will definitly
3364       *     fail, <code>true</code> if it will likely succeed
3365       *
3366       * @see Component#requestFocus(boolean)
3367       *
3368       * @since 1.4
3369       */
3370      public boolean requestFocus(boolean temporary)
3371      {
3372        return super.requestFocus(temporary);
3373      }
3374    
3375      /**
3376       * Requests that this component gets the input focus if the top level
3377       * window that contains this component has the focus and the
3378       * requestFocusEnabled property is set to <code>true</code>.
3379       *
3380       * The preconditions that have to be met to become a focus owner is that
3381       * the component must be displayable, visible and focusable.
3382       *
3383       * Note that this signals only a request for becoming focused. There are
3384       * situations in which it is not possible to get the focus. So developers
3385       * should not assume that the component has the focus until it receives
3386       * a {@link java.awt.event.FocusEvent} with a value of
3387       * {@link java.awt.event.FocusEvent#FOCUS_GAINED}.
3388       *
3389       * @return <code>false</code> if the focus change request will definitly
3390       *     fail, <code>true</code> if it will likely succeed
3391       *
3392       * @see Component#requestFocusInWindow()
3393       */
3394      public boolean requestFocusInWindow()
3395      {
3396        if (isRequestFocusEnabled())
3397          return super.requestFocusInWindow();
3398        else
3399          return false;
3400      }
3401    
3402      /**
3403       * This method is overridden to make it public so that it can be used
3404       * by look and feel implementations.
3405       *
3406       * You should not use this method directly. Instead you are strongly
3407       * encouraged to call {@link #requestFocus()} or 
3408       * {@link #requestFocusInWindow()} instead.
3409       *
3410       * @param temporary if the focus change is temporary
3411       *
3412       * @return <code>false</code> if the focus change request will definitly
3413       *     fail, <code>true</code> if it will likely succeed
3414       *
3415       * @see Component#requestFocus(boolean)
3416       *
3417       * @since 1.4
3418       */
3419      protected boolean requestFocusInWindow(boolean temporary)
3420      {
3421        return super.requestFocusInWindow(temporary);
3422      }
3423    
3424      /**
3425       * Receives notification if this component is added to a parent component.
3426       *
3427       * Notification is sent to all registered AncestorListeners about the
3428       * new parent.
3429       *
3430       * This method sets up ActionListeners for all registered KeyStrokes of
3431       * this component in the chain of parent components.
3432       *
3433       * A PropertyChange event is fired to indicate that the ancestor property
3434       * has changed.
3435       *
3436       * This method is used internally and should not be used in applications.
3437       */
3438      public void addNotify()
3439      {
3440        // Register the WHEN_IN_FOCUSED_WINDOW keyboard bindings
3441        // Note that here we unregister all bindings associated with
3442        // this component and then re-register them.  This may be more than
3443        // necessary if the top-level ancestor hasn't changed.  Should
3444        // maybe improve this.
3445        KeyboardManager km = KeyboardManager.getManager();
3446        km.clearBindingsForComp(this);
3447        km.registerEntireMap((ComponentInputMap)
3448                             this.getInputMap(WHEN_IN_FOCUSED_WINDOW));
3449        super.addNotify();
3450    
3451        // Notify AncestorListeners.
3452        fireAncestorEvent(this, AncestorEvent.ANCESTOR_ADDED);
3453    
3454        // fire property change event for 'ancestor'
3455        firePropertyChange("ancestor", null, getParent());
3456      }
3457    
3458      /**
3459       * Receives notification that this component no longer has a parent.
3460       *
3461       * This method sends an AncestorEvent to all registered AncestorListeners,
3462       * notifying them that the parent is gone.
3463       *
3464       * The keybord actions of this component are removed from the parent and
3465       * its ancestors.
3466       *
3467       * A PropertyChangeEvent is fired to indicate that the 'ancestor' property
3468       * has changed.
3469       *
3470       * This method is called before the component is actually removed from
3471       * its parent, so the parent is still visible through 
3472       * {@link Component#getParent}.
3473       */
3474      public void removeNotify()
3475      {
3476        super.removeNotify();
3477    
3478        KeyboardManager.getManager().clearBindingsForComp(this);
3479        
3480        // Notify ancestor listeners.
3481        fireAncestorEvent(this, AncestorEvent.ANCESTOR_REMOVED);
3482    
3483        // fire property change event for 'ancestor'
3484        firePropertyChange("ancestor", getParent(), null);
3485      }
3486    
3487      /**
3488       * Returns <code>true</code> if the coordinates (x, y) lie within
3489       * the bounds of this component and <code>false</code> otherwise.
3490       * x and y are relative to the coordinate space of the component.
3491       *
3492       * @param x the X coordinate of the point to check
3493       * @param y the Y coordinate of the point to check
3494       *
3495       * @return <code>true</code> if the specified point lies within the bounds
3496       *     of this component, <code>false</code> otherwise
3497       */
3498      public boolean contains(int x, int y)
3499      {
3500        if (ui == null)
3501          return super.contains(x, y);
3502        else
3503          return ui.contains(this, x, y);
3504      }
3505    
3506      /**
3507       * Disables this component.
3508       *
3509       * @deprecated replaced by {@link #setEnabled(boolean)}
3510       */
3511      public void disable()
3512      {
3513        super.disable();
3514      }
3515    
3516      /**
3517       * Enables this component.
3518       *
3519       * @deprecated replaced by {@link #setEnabled(boolean)}
3520       */
3521      public void enable()
3522      {
3523        super.enable();
3524      }
3525    
3526      /**
3527       * Returns the Graphics context for this component. This can be used
3528       * to draw on a component.
3529       *
3530       * @return the Graphics context for this component
3531       */
3532      public Graphics getGraphics()
3533      {
3534        return super.getGraphics();
3535      }
3536    
3537      /**
3538       * Returns the X coordinate of the upper left corner of this component.
3539       * Prefer this method over {@link #getBounds} or {@link #getLocation}
3540       * because it does not cause any heap allocation.
3541       *
3542       * @return the X coordinate of the upper left corner of the component
3543       */
3544      public int getX()
3545      {
3546        return super.getX();
3547      }
3548    
3549      /**
3550       * Returns the Y coordinate of the upper left corner of this component.
3551       * Prefer this method over {@link #getBounds} or {@link #getLocation}
3552       * because it does not cause any heap allocation.
3553       *
3554       * @return the Y coordinate of the upper left corner of the component
3555       */
3556      public int getY()
3557      {
3558        return super.getY();
3559      }
3560    
3561      /**
3562       * Returns the height of this component. Prefer this method over
3563       * {@link #getBounds} or {@link #getSize} because it does not cause
3564       * any heap allocation.
3565       *
3566       * @return the height of the component
3567       */
3568      public int getHeight()
3569      {
3570        return super.getHeight();
3571      }
3572    
3573      /**
3574       * Returns the width of this component. Prefer this method over
3575       * {@link #getBounds} or {@link #getSize} because it does not cause
3576       * any heap allocation.
3577       *
3578       * @return the width of the component
3579       */
3580      public int getWidth()
3581      {
3582        return super.getWidth();
3583      }
3584    
3585      /**
3586       * Prints this component to the given Graphics context. A call to this
3587       * method results in calls to the methods {@link #printComponent},
3588       * {@link #printBorder} and {@link #printChildren} in this order.
3589       *
3590       * Double buffering is temporarily turned off so the painting goes directly
3591       * to the supplied Graphics context.
3592       *
3593       * @param g the Graphics context to print onto
3594       */
3595      public void print(Graphics g)
3596      {
3597        boolean doubleBufferState = isDoubleBuffered();
3598        setDoubleBuffered(false);
3599        printComponent(g);
3600        printBorder(g);
3601        printChildren(g);
3602        setDoubleBuffered(doubleBufferState);
3603      }
3604    
3605      /**
3606       * Prints this component to the given Graphics context. This invokes
3607       * {@link #print}.
3608       *
3609       * @param g the Graphics context to print onto
3610       */
3611      public void printAll(Graphics g)
3612      {
3613        print(g);
3614      }
3615    
3616      /**
3617       * Prints this component to the specified Graphics context. The default
3618       * behaviour is to invoke {@link #paintComponent}. Override this
3619       * if you want special behaviour for printing.
3620       *
3621       * @param g the Graphics context to print onto
3622       *
3623       * @since 1.3
3624       */
3625      protected void printComponent(Graphics g)
3626      {
3627        paintComponent(g);
3628      }
3629    
3630      /**
3631       * Print this component's children to the specified Graphics context.
3632       * The default behaviour is to invoke {@link #paintChildren}. Override this
3633       * if you want special behaviour for printing.
3634       *
3635       * @param g the Graphics context to print onto
3636       *
3637       * @since 1.3
3638       */
3639      protected void printChildren(Graphics g)
3640      {
3641        paintChildren(g);
3642      }
3643    
3644      /**
3645       * Print this component's border to the specified Graphics context.
3646       * The default behaviour is to invoke {@link #paintBorder}. Override this
3647       * if you want special behaviour for printing.
3648       *
3649       * @param g the Graphics context to print onto
3650       *
3651       * @since 1.3
3652       */
3653      protected void printBorder(Graphics g)
3654      {
3655        paintBorder(g);
3656      }
3657    
3658      /**
3659       * Processes mouse motion event, like dragging and moving.
3660       *
3661       * @param ev the MouseEvent describing the mouse motion
3662       */
3663      protected void processMouseMotionEvent(MouseEvent ev)
3664      {
3665        super.processMouseMotionEvent(ev);
3666      }
3667    
3668      /**
3669       * Moves and resizes the component.
3670       *
3671       * @param x the new horizontal location
3672       * @param y the new vertial location
3673       * @param w the new width
3674       * @param h the new height
3675       */
3676      public void reshape(int x, int y, int w, int h)
3677      {
3678        int oldX = getX();
3679        int oldY = getY();
3680        super.reshape(x, y, w, h);
3681        // Notify AncestorListeners.
3682        if (oldX != getX() || oldY != getY())
3683          fireAncestorEvent(this, AncestorEvent.ANCESTOR_MOVED);
3684      }
3685    
3686      /**
3687       * Fires an AncestorEvent to this component's and all of its child
3688       * component's AncestorListeners.
3689       *
3690       * @param ancestor the component that triggered the event
3691       * @param id the kind of ancestor event that should be fired
3692       */
3693      void fireAncestorEvent(JComponent ancestor, int id)
3694      {
3695        // Fire event for registered ancestor listeners of this component.
3696        AncestorListener[] listeners = getAncestorListeners();
3697        if (listeners.length > 0)
3698          {
3699            AncestorEvent ev = new AncestorEvent(this, id,
3700                                                 ancestor, ancestor.getParent());
3701            for (int i = 0; i < listeners.length; i++)
3702              {
3703                switch (id)
3704                  {
3705                  case AncestorEvent.ANCESTOR_MOVED:
3706                    listeners[i].ancestorMoved(ev);
3707                    break;
3708                  case AncestorEvent.ANCESTOR_ADDED:
3709                    listeners[i].ancestorAdded(ev);
3710                    break;
3711                  case AncestorEvent.ANCESTOR_REMOVED:
3712                    listeners[i].ancestorRemoved(ev);
3713                    break;
3714                  }
3715              }
3716          }
3717        // Dispatch event to all children.
3718        int numChildren = getComponentCount();
3719        for (int i = 0; i < numChildren; i++)
3720          {
3721            Component child = getComponent(i);
3722            if (! (child instanceof JComponent))
3723              continue;
3724            JComponent jc = (JComponent) child;
3725            jc.fireAncestorEvent(ancestor, id);
3726          }
3727      }
3728      
3729      /**
3730       * This is the method that gets called when the WHEN_IN_FOCUSED_WINDOW map
3731       * is changed.
3732       *
3733       * @param changed the JComponent associated with the WHEN_IN_FOCUSED_WINDOW
3734       *        map
3735       */
3736      void updateComponentInputMap(ComponentInputMap changed)
3737      {
3738        // Since you can change a component's input map via
3739        // setInputMap, we have to check if <code>changed</code>
3740        // is still in our WHEN_IN_FOCUSED_WINDOW map hierarchy
3741        InputMap curr = getInputMap(WHEN_IN_FOCUSED_WINDOW);
3742        while (curr != null && curr != changed)
3743          curr = curr.getParent();
3744        
3745        // If curr is null then changed is not in the hierarchy
3746        if (curr == null)
3747          return;
3748        
3749        // Now we have to update the keyboard manager's hashtable
3750        KeyboardManager km = KeyboardManager.getManager();
3751        
3752        // This is a poor strategy, should be improved.  We currently 
3753        // delete all the old bindings for the component and then register
3754        // the current bindings.
3755        km.clearBindingsForComp(changed.getComponent());
3756        km.registerEntireMap((ComponentInputMap) 
3757                             getInputMap(WHEN_IN_FOCUSED_WINDOW));
3758      }
3759    
3760      /**
3761       * Helper method for
3762       * {@link LookAndFeel#installProperty(JComponent, String, Object)}.
3763       * 
3764       * @param propertyName the name of the property
3765       * @param value the value of the property
3766       *
3767       * @throws IllegalArgumentException if the specified property cannot be set
3768       *         by this method
3769       * @throws ClassCastException if the property value does not match the
3770       *         property type
3771       * @throws NullPointerException if <code>c</code> or
3772       *         <code>propertyValue</code> is <code>null</code>
3773       */
3774      void setUIProperty(String propertyName, Object value)
3775      {
3776        if (propertyName.equals("opaque"))
3777          {
3778            if (! clientOpaqueSet)
3779              {
3780                setOpaque(((Boolean) value).booleanValue());
3781                clientOpaqueSet = false;
3782              }
3783          }
3784        else if (propertyName.equals("autoscrolls"))
3785          {
3786            if (! clientAutoscrollsSet)
3787              {
3788                setAutoscrolls(((Boolean) value).booleanValue());
3789                clientAutoscrollsSet = false;
3790              }
3791          }
3792        else
3793          {
3794            throw new IllegalArgumentException
3795                ("Unsupported property for LookAndFeel.installProperty(): "
3796                 + propertyName);
3797          }
3798      }
3799    }