001    /* Component.java -- a graphics component
002       Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2006
003       Free Software Foundation
004    
005    This file is part of GNU Classpath.
006    
007    GNU Classpath is free software; you can redistribute it and/or modify
008    it under the terms of the GNU General Public License as published by
009    the Free Software Foundation; either version 2, or (at your option)
010    any later version.
011    
012    GNU Classpath is distributed in the hope that it will be useful, but
013    WITHOUT ANY WARRANTY; without even the implied warranty of
014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015    General Public License for more details.
016    
017    You should have received a copy of the GNU General Public License
018    along with GNU Classpath; see the file COPYING.  If not, write to the
019    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
020    02110-1301 USA.
021    
022    Linking this library statically or dynamically with other modules is
023    making a combined work based on this library.  Thus, the terms and
024    conditions of the GNU General Public License cover the whole
025    combination.
026    
027    As a special exception, the copyright holders of this library give you
028    permission to link this library with independent modules to produce an
029    executable, regardless of the license terms of these independent
030    modules, and to copy and distribute the resulting executable under
031    terms of your choice, provided that you also meet, for each linked
032    independent module, the terms and conditions of the license of that
033    module.  An independent module is a module which is not derived from
034    or based on this library.  If you modify this library, you may extend
035    this exception to your version of the library, but you are not
036    obligated to do so.  If you do not wish to do so, delete this
037    exception statement from your version. */
038    
039    
040    package java.awt;
041    
042    //import gnu.java.awt.dnd.peer.gtk.GtkDropTargetContextPeer;
043    
044    import gnu.java.awt.ComponentReshapeEvent;
045    
046    import java.awt.dnd.DropTarget;
047    import java.awt.event.ActionEvent;
048    import java.awt.event.AdjustmentEvent;
049    import java.awt.event.ComponentEvent;
050    import java.awt.event.ComponentListener;
051    import java.awt.event.FocusEvent;
052    import java.awt.event.FocusListener;
053    import java.awt.event.HierarchyBoundsListener;
054    import java.awt.event.HierarchyEvent;
055    import java.awt.event.HierarchyListener;
056    import java.awt.event.InputEvent;
057    import java.awt.event.InputMethodEvent;
058    import java.awt.event.InputMethodListener;
059    import java.awt.event.KeyEvent;
060    import java.awt.event.KeyListener;
061    import java.awt.event.MouseEvent;
062    import java.awt.event.MouseListener;
063    import java.awt.event.MouseMotionListener;
064    import java.awt.event.MouseWheelEvent;
065    import java.awt.event.MouseWheelListener;
066    import java.awt.event.PaintEvent;
067    import java.awt.event.WindowEvent;
068    import java.awt.im.InputContext;
069    import java.awt.im.InputMethodRequests;
070    import java.awt.image.BufferStrategy;
071    import java.awt.image.ColorModel;
072    import java.awt.image.ImageObserver;
073    import java.awt.image.ImageProducer;
074    import java.awt.image.VolatileImage;
075    import java.awt.peer.ComponentPeer;
076    import java.awt.peer.LightweightPeer;
077    import java.beans.PropertyChangeEvent;
078    import java.beans.PropertyChangeListener;
079    import java.beans.PropertyChangeSupport;
080    import java.io.IOException;
081    import java.io.ObjectInputStream;
082    import java.io.ObjectOutputStream;
083    import java.io.PrintStream;
084    import java.io.PrintWriter;
085    import java.io.Serializable;
086    import java.lang.reflect.Array;
087    import java.util.Collections;
088    import java.util.EventListener;
089    import java.util.HashSet;
090    import java.util.Iterator;
091    import java.util.Locale;
092    import java.util.Set;
093    import java.util.Vector;
094    
095    import javax.accessibility.Accessible;
096    import javax.accessibility.AccessibleComponent;
097    import javax.accessibility.AccessibleContext;
098    import javax.accessibility.AccessibleRole;
099    import javax.accessibility.AccessibleState;
100    import javax.accessibility.AccessibleStateSet;
101    
102    /**
103     * The root of all evil. All graphical representations are subclasses of this
104     * giant class, which is designed for screen display and user interaction.
105     * This class can be extended directly to build a lightweight component (one
106     * not associated with a native window); lightweight components must reside
107     * inside a heavyweight window.
108     *
109     * <p>This class is Serializable, which has some big implications. A user can
110     * save the state of all graphical components in one VM, and reload them in
111     * another. Note that this class will only save Serializable listeners, and
112     * ignore the rest, without causing any serialization exceptions. However, by
113     * making a listener serializable, and adding it to another element, you link
114     * in that entire element to the state of this component. To get around this,
115     * use the idiom shown in the example below - make listeners non-serializable
116     * in inner classes, rather than using this object itself as the listener, if
117     * external objects do not need to save the state of this object.
118     *
119     * <pre>
120     * import java.awt.*;
121     * import java.awt.event.*;
122     * import java.io.Serializable;
123     * class MyApp implements Serializable
124     * {
125     *   BigObjectThatShouldNotBeSerializedWithAButton bigOne;
126     *   // Serializing aButton will not suck in an instance of MyApp, with its
127     *   // accompanying field bigOne.
128     *   Button aButton = new Button();
129     *   class MyActionListener implements ActionListener
130     *   {
131     *     public void actionPerformed(ActionEvent e)
132     *     {
133     *       System.out.println("Hello There");
134     *     }
135     *   }
136     *   MyApp()
137     *   {
138     *     aButton.addActionListener(new MyActionListener());
139     *   }
140     * }
141     * </pre>
142     *
143     * <p>Status: Incomplete. The event dispatch mechanism is implemented. All
144     * other methods defined in the J2SE 1.3 API javadoc exist, but are mostly
145     * incomplete or only stubs; except for methods relating to the Drag and
146     * Drop, Input Method, and Accessibility frameworks: These methods are
147     * present but commented out.
148     *
149     * @author original author unknown
150     * @author Eric Blake (ebb9@email.byu.edu)
151     * @since 1.0
152     * @status still missing 1.4 support
153     */
154    public abstract class Component
155      implements ImageObserver, MenuContainer, Serializable
156    {
157      // Word to the wise - this file is huge. Search for '\f' (^L) for logical
158      // sectioning by fields, public API, private API, and nested classes.
159    
160    
161      /**
162       * Compatible with JDK 1.0+.
163       */
164      private static final long serialVersionUID = -7644114512714619750L;
165    
166      /**
167       * Constant returned by the <code>getAlignmentY</code> method to indicate
168       * that the component wishes to be aligned to the top relative to
169       * other components.
170       *
171       * @see #getAlignmentY()
172       */
173      public static final float TOP_ALIGNMENT = 0;
174    
175      /**
176       * Constant returned by the <code>getAlignmentY</code> and
177       * <code>getAlignmentX</code> methods to indicate
178       * that the component wishes to be aligned to the center relative to
179       * other components.
180       *
181       * @see #getAlignmentX()
182       * @see #getAlignmentY()
183       */
184      public static final float CENTER_ALIGNMENT = 0.5f;
185    
186      /**
187       * Constant returned by the <code>getAlignmentY</code> method to indicate
188       * that the component wishes to be aligned to the bottom relative to
189       * other components.
190       *
191       * @see #getAlignmentY()
192       */
193      public static final float BOTTOM_ALIGNMENT = 1;
194    
195      /**
196       * Constant returned by the <code>getAlignmentX</code> method to indicate
197       * that the component wishes to be aligned to the right relative to
198       * other components.
199       *
200       * @see #getAlignmentX()
201       */
202      public static final float RIGHT_ALIGNMENT = 1;
203    
204      /**
205       * Constant returned by the <code>getAlignmentX</code> method to indicate
206       * that the component wishes to be aligned to the left relative to
207       * other components.
208       *
209       * @see #getAlignmentX()
210       */
211      public static final float LEFT_ALIGNMENT = 0;
212    
213      /**
214       * Make the treelock a String so that it can easily be identified
215       * in debug dumps. We clone the String in order to avoid a conflict in
216       * the unlikely event that some other package uses exactly the same string
217       * as a lock object.
218       */
219      static final Object treeLock = new String("AWT_TREE_LOCK");
220    
221      /**
222       * The default maximum size.
223       */
224      private static final Dimension DEFAULT_MAX_SIZE 
225                                 = new Dimension(Short.MAX_VALUE, Short.MAX_VALUE);
226    
227      // Serialized fields from the serialization spec.
228    
229      /**
230       * The x position of the component in the parent's coordinate system.
231       *
232       * @see #getLocation()
233       * @serial the x position
234       */
235      int x;
236    
237      /**
238       * The y position of the component in the parent's coordinate system.
239       *
240       * @see #getLocation()
241       * @serial the y position
242       */
243      int y;
244    
245      /**
246       * The component width.
247       *
248       * @see #getSize()
249       * @serial the width
250       */
251      int width;
252    
253      /**
254       * The component height.
255       *
256       * @see #getSize()
257       * @serial the height
258       */
259      int height;
260    
261      /**
262       * The foreground color for the component. This may be null.
263       *
264       * @see #getForeground()
265       * @see #setForeground(Color)
266       * @serial the foreground color
267       */
268      Color foreground;
269    
270      /**
271       * The background color for the component. This may be null.
272       *
273       * @see #getBackground()
274       * @see #setBackground(Color)
275       * @serial the background color
276       */
277      Color background;
278    
279      /**
280       * The default font used in the component. This may be null.
281       *
282       * @see #getFont()
283       * @see #setFont(Font)
284       * @serial the font
285       */
286      Font font;
287    
288      /**
289       * The font in use by the peer, or null if there is no peer.
290       *
291       * @serial the peer's font
292       */
293      Font peerFont;
294    
295      /**
296       * The cursor displayed when the pointer is over this component. This may
297       * be null.
298       *
299       * @see #getCursor()
300       * @see #setCursor(Cursor)
301       */
302      Cursor cursor;
303    
304      /**
305       * The locale for the component.
306       *
307       * @see #getLocale()
308       * @see #setLocale(Locale)
309       */
310      Locale locale = Locale.getDefault ();
311    
312      /**
313       * True if the object should ignore repaint events (usually because it is
314       * not showing).
315       *
316       * @see #getIgnoreRepaint()
317       * @see #setIgnoreRepaint(boolean)
318       * @serial true to ignore repaints
319       * @since 1.4
320       */
321      boolean ignoreRepaint;
322    
323      /**
324       * True when the object is visible (although it is only showing if all
325       * ancestors are likewise visible). For component, this defaults to true.
326       *
327       * @see #isVisible()
328       * @see #setVisible(boolean)
329       * @serial true if visible
330       */
331      boolean visible = true;
332    
333      /**
334       * True if the object is enabled, meaning it can interact with the user.
335       * For component, this defaults to true.
336       *
337       * @see #isEnabled()
338       * @see #setEnabled(boolean)
339       * @serial true if enabled
340       */
341      boolean enabled = true;
342    
343      /**
344       * True if the object is valid. This is set to false any time a size
345       * adjustment means the component need to be layed out again.
346       *
347       * @see #isValid()
348       * @see #validate()
349       * @see #invalidate()
350       * @serial true if layout is valid
351       */
352      boolean valid;
353    
354      /**
355       * The DropTarget for drag-and-drop operations.
356       *
357       * @see #getDropTarget()
358       * @see #setDropTarget(DropTarget)
359       * @serial the drop target, or null
360       * @since 1.2
361       */
362      DropTarget dropTarget;
363    
364      /**
365       * The list of popup menus for this component.
366       *
367       * @see #add(PopupMenu)
368       * @serial the list of popups
369       */
370      Vector popups;
371    
372      /**
373       * The component's name. May be null, in which case a default name is
374       * generated on the first use.
375       *
376       * @see #getName()
377       * @see #setName(String)
378       * @serial the name
379       */
380      String name;
381    
382      /**
383       * True once the user has set the name. Note that the user may set the name
384       * to null.
385       *
386       * @see #name
387       * @see #getName()
388       * @see #setName(String)
389       * @serial true if the name has been explicitly set
390       */
391      boolean nameExplicitlySet;
392    
393      /**
394       * Indicates if the object can be focused. Defaults to true for components.
395       *
396       * @see #isFocusable()
397       * @see #setFocusable(boolean)
398       * @since 1.4
399       */
400      boolean focusable = true;
401    
402      /**
403       * Tracks whether this component's {@link #isFocusTraversable}
404       * method has been overridden.
405       *
406       * @since 1.4
407       */
408      int isFocusTraversableOverridden;
409    
410      /**
411       * The focus traversal keys, if not inherited from the parent or
412       * default keyboard focus manager. These sets will contain only
413       * AWTKeyStrokes that represent press and release events to use as
414       * focus control.
415       *
416       * @see #getFocusTraversalKeys(int)
417       * @see #setFocusTraversalKeys(int, Set)
418       * @since 1.4
419       */
420      Set[] focusTraversalKeys;
421    
422      /**
423       * True if focus traversal keys are enabled. This defaults to true for
424       * Component. If this is true, keystrokes in focusTraversalKeys are trapped
425       * and processed automatically rather than being passed on to the component.
426       *
427       * @see #getFocusTraversalKeysEnabled()
428       * @see #setFocusTraversalKeysEnabled(boolean)
429       * @since 1.4
430       */
431      boolean focusTraversalKeysEnabled = true;
432    
433      /**
434       * Cached information on the minimum size. Should have been transient.
435       *
436       * @serial ignore
437       */
438      Dimension minSize;
439    
440      /**
441       * Flag indicating whether the minimum size for the component has been set
442       * by a call to {@link #setMinimumSize(Dimension)} with a non-null value.
443       */
444      boolean minSizeSet;
445      
446      /**
447       * The maximum size for the component.
448       * @see #setMaximumSize(Dimension)
449       */
450      Dimension maxSize;
451      
452      /**
453       * A flag indicating whether the maximum size for the component has been set
454       * by a call to {@link #setMaximumSize(Dimension)} with a non-null value.
455       */
456      boolean maxSizeSet;
457      
458      /**
459       * Cached information on the preferred size. Should have been transient.
460       *
461       * @serial ignore
462       */
463      Dimension prefSize;
464    
465      /**
466       * Flag indicating whether the preferred size for the component has been set
467       * by a call to {@link #setPreferredSize(Dimension)} with a non-null value.
468       */
469      boolean prefSizeSet;
470    
471      /**
472       * Set to true if an event is to be handled by this component, false if
473       * it is to be passed up the hierarcy.
474       *
475       * @see #dispatchEvent(AWTEvent)
476       * @serial true to process event locally
477       */
478      boolean newEventsOnly;
479    
480      /**
481       * Set by subclasses to enable event handling of particular events, and
482       * left alone when modifying listeners. For component, this defaults to
483       * enabling only input methods.
484       *
485       * @see #enableInputMethods(boolean)
486       * @see AWTEvent
487       * @serial the mask of events to process
488       */
489      long eventMask = AWTEvent.INPUT_ENABLED_EVENT_MASK;
490    
491      /**
492       * Describes all registered PropertyChangeListeners.
493       *
494       * @see #addPropertyChangeListener(PropertyChangeListener)
495       * @see #removePropertyChangeListener(PropertyChangeListener)
496       * @see #firePropertyChange(String, Object, Object)
497       * @serial the property change listeners
498       * @since 1.2
499       */
500      PropertyChangeSupport changeSupport;
501    
502      /**
503       * True if the component has been packed (layed out).
504       *
505       * @serial true if this is packed
506       */
507      boolean isPacked;
508    
509      /**
510       * The serialization version for this class. Currently at version 4.
511       *
512       * XXX How do we handle prior versions?
513       *
514       * @serial the serialization version
515       */
516      int componentSerializedDataVersion = 4;
517    
518      /**
519       * The accessible context associated with this component. This is only set
520       * by subclasses.
521       *
522       * @see #getAccessibleContext()
523       * @serial the accessibility context
524       * @since 1.2
525       */
526      AccessibleContext accessibleContext;
527    
528    
529      // Guess what - listeners are special cased in serialization. See
530      // readObject and writeObject.
531    
532      /** Component listener chain. */
533      transient ComponentListener componentListener;
534    
535      /** Focus listener chain. */
536      transient FocusListener focusListener;
537    
538      /** Key listener chain. */
539      transient KeyListener keyListener;
540    
541      /** Mouse listener chain. */
542      transient MouseListener mouseListener;
543    
544      /** Mouse motion listener chain. */
545      transient MouseMotionListener mouseMotionListener;
546    
547      /**
548       * Mouse wheel listener chain.
549       *
550       * @since 1.4
551       */
552      transient MouseWheelListener mouseWheelListener;
553    
554      /**
555       * Input method listener chain.
556       *
557       * @since 1.2
558       */
559      transient InputMethodListener inputMethodListener;
560    
561      /**
562       * Hierarcy listener chain.
563       *
564       * @since 1.3
565       */
566      transient HierarchyListener hierarchyListener;
567    
568      /**
569       * Hierarcy bounds listener chain.
570       *
571       * @since 1.3
572       */
573      transient HierarchyBoundsListener hierarchyBoundsListener;
574    
575      // Anything else is non-serializable, and should be declared "transient".
576    
577      /** The parent. */
578      transient Container parent;
579    
580      /** The associated native peer. */
581      transient ComponentPeer peer;
582    
583      /** The preferred component orientation. */
584      transient ComponentOrientation componentOrientation = ComponentOrientation.UNKNOWN;
585    
586      /**
587       * The associated graphics configuration.
588       *
589       * @since 1.4
590       */
591      transient GraphicsConfiguration graphicsConfig;
592    
593      /**
594       * The buffer strategy for repainting.
595       *
596       * @since 1.4
597       */
598      transient BufferStrategy bufferStrategy;
599    
600      /**
601       * The number of hierarchy listeners of this container plus all of its
602       * children. This is needed for efficient handling of HierarchyEvents.
603       * These must be propagated to all child components with HierarchyListeners
604       * attached. To avoid traversal of the whole subtree, we keep track of
605       * the number of HierarchyListeners here and only walk the paths that
606       * actually have listeners.
607       */
608      int numHierarchyListeners;
609      int numHierarchyBoundsListeners;
610    
611      /**
612       * true if requestFocus was called on this component when its
613       * top-level ancestor was not focusable.
614       */
615      private transient FocusEvent pendingFocusRequest = null;
616    
617      /**
618       * The system properties that affect image updating.
619       */
620      private static transient boolean incrementalDraw;
621      private static transient Long redrawRate;
622    
623      static
624      {
625        incrementalDraw = Boolean.getBoolean ("awt.image.incrementalDraw");
626        redrawRate = Long.getLong ("awt.image.redrawrate");
627      }
628    
629      // Public and protected API.
630    
631      /**
632       * Default constructor for subclasses. When Component is extended directly,
633       * it forms a lightweight component that must be hosted in an opaque native
634       * container higher in the tree.
635       */
636      protected Component()
637      {
638        // Nothing to do here.
639      }
640    
641      /**
642       * Returns the name of this component.
643       *
644       * @return the name of this component
645       * @see #setName(String)
646       * @since 1.1
647       */
648      public String getName()
649      {
650        if (name == null && ! nameExplicitlySet)
651          name = generateName();
652        return name;
653      }
654    
655      /**
656       * Sets the name of this component to the specified name (this is a bound
657       * property with the name 'name').
658       *
659       * @param name the new name (<code>null</code> permitted).
660       * @see #getName()
661       * @since 1.1
662       */
663      public void setName(String name)
664      {
665        nameExplicitlySet = true;
666        String old = this.name;
667        this.name = name;
668        firePropertyChange("name", old, name);
669      }
670    
671      /**
672       * Returns the parent of this component.
673       *
674       * @return the parent of this component
675       */
676      public Container getParent()
677      {
678        return parent;
679      }
680    
681      /**
682       * Returns the native windowing system peer for this component. Only the
683       * platform specific implementation code should call this method.
684       *
685       * @return the peer for this component
686       * @deprecated user programs should not directly manipulate peers; use
687       *             {@link #isDisplayable()} instead
688       */
689      // Classpath's Gtk peers rely on this.
690      public ComponentPeer getPeer()
691      {
692        return peer;
693      }
694    
695      /**
696       * Set the associated drag-and-drop target, which receives events when this
697       * is enabled.
698       *
699       * @param dt the new drop target
700       * @see #isEnabled()
701       */
702      public void setDropTarget(DropTarget dt)
703      {
704        this.dropTarget = dt;
705        
706        if (peer != null)
707          dropTarget.addNotify(peer);
708      }
709    
710      /**
711       * Gets the associated drag-and-drop target, if there is one.
712       *
713       * @return the drop target
714       */
715      public DropTarget getDropTarget()
716      {
717        return dropTarget;
718      }
719    
720      /**
721       * Returns the graphics configuration of this component, if there is one.
722       * If it has not been set, it is inherited from the parent.
723       *
724       * @return the graphics configuration, or null
725       * @since 1.3
726       */
727      public GraphicsConfiguration getGraphicsConfiguration()
728      {
729        GraphicsConfiguration conf = null;
730        synchronized (getTreeLock())
731          {
732            if (graphicsConfig != null)
733              {
734                conf = graphicsConfig;
735              }
736            else
737              {
738                Component par = getParent();
739                if (par != null)
740                  {
741                    conf = parent.getGraphicsConfiguration();
742                  }
743              }
744          }
745        return conf;
746      }
747    
748      /**
749       * Returns the object used for synchronization locks on this component
750       * when performing tree and layout functions.
751       *
752       * @return the synchronization lock for this component
753       */
754      public final Object getTreeLock()
755      {
756        return treeLock;
757      }
758    
759      /**
760       * Returns the toolkit in use for this component. The toolkit is associated
761       * with the frame this component belongs to.
762       *
763       * @return the toolkit for this component
764       */
765      public Toolkit getToolkit()
766      {
767        // Only heavyweight peers can handle this.
768        ComponentPeer p = peer;
769        Component comp = this;
770        while (p instanceof LightweightPeer)
771          {
772            comp = comp.parent;
773            p = comp == null ? null : comp.peer;
774          }
775    
776        Toolkit tk = null;
777        if (p != null)
778          {
779            tk = peer.getToolkit();
780          }
781        if (tk == null)
782          tk = Toolkit.getDefaultToolkit();
783        return tk;
784      }
785    
786      /**
787       * Tests whether or not this component is valid. A invalid component needs
788       * to have its layout redone.
789       *
790       * @return true if this component is valid
791       * @see #validate()
792       * @see #invalidate()
793       */
794      public boolean isValid()
795      {
796        // Tests show that components are invalid as long as they are not showing, even after validate()
797        // has been called on them.
798        return peer != null && valid;
799      }
800    
801      /**
802       * Tests if the component is displayable. It must be connected to a native
803       * screen resource.  This reduces to checking that peer is not null.  A 
804       * containment  hierarchy is made displayable when a window is packed or 
805       * made visible.
806       *
807       * @return true if the component is displayable
808       * @see Container#add(Component)
809       * @see Container#remove(Component)
810       * @see Window#pack()
811       * @see Window#show()
812       * @see Window#dispose()
813       * @since 1.2
814       */
815      public boolean isDisplayable()
816      {
817        return peer != null;
818      }
819    
820      /**
821       * Tests whether or not this component is visible. Except for top-level
822       * frames, components are initially visible.
823       *
824       * @return true if the component is visible
825       * @see #setVisible(boolean)
826       */
827      public boolean isVisible()
828      {
829        return visible;
830      }
831    
832      /**
833       * Tests whether or not this component is actually being shown on
834       * the screen. This will be true if and only if it this component is
835       * visible and its parent components are all visible.
836       *
837       * @return true if the component is showing on the screen
838       * @see #setVisible(boolean)
839       */
840      public boolean isShowing()
841      {
842        Component par = parent;
843        return visible && peer != null && (par == null || par.isShowing());
844      }
845    
846      /**
847       * Tests whether or not this component is enabled. Components are enabled
848       * by default, and must be enabled to receive user input or generate events.
849       *
850       * @return true if the component is enabled
851       * @see #setEnabled(boolean)
852       */
853      public boolean isEnabled()
854      {
855        return enabled;
856      }
857    
858      /**
859       * Enables or disables this component. The component must be enabled to
860       * receive events (except that lightweight components always receive mouse
861       * events).
862       *
863       * @param enabled true to enable this component
864       * 
865       * @see #isEnabled()
866       * @see #isLightweight()
867       * 
868       * @since 1.1
869       */
870      public void setEnabled(boolean enabled)
871      {
872        enable(enabled);
873      }
874    
875      /**
876       * Enables this component.
877       *
878       * @deprecated use {@link #setEnabled(boolean)} instead
879       */
880      public void enable()
881      {
882        if (! enabled)
883          {
884            // Need to lock the tree here, because the peers are involved.
885            synchronized (getTreeLock())
886              {
887                enabled = true;
888                ComponentPeer p = peer;
889                if (p != null)
890                  p.enable();
891              }
892          }
893      }
894    
895      /**
896       * Enables or disables this component.
897       *
898       * @param enabled true to enable this component
899       * 
900       * @deprecated use {@link #setEnabled(boolean)} instead
901       */
902      public void enable(boolean enabled)
903      {
904        if (enabled)
905          enable();
906        else
907          disable();
908      }
909    
910      /**
911       * Disables this component.
912       *
913       * @deprecated use {@link #setEnabled(boolean)} instead
914       */
915      public void disable()
916      {
917        if (enabled)
918          {
919            // Need to lock the tree here, because the peers are involved.
920            synchronized (getTreeLock())
921              {
922                enabled = false;
923                ComponentPeer p = peer;
924                if (p != null)
925                  p.disable();
926              }
927          }
928      }
929    
930      /**
931       * Checks if this image is painted to an offscreen image buffer that is
932       * later copied to screen (double buffering reduces flicker). This version
933       * returns false, so subclasses must override it if they provide double
934       * buffering.
935       *
936       * @return true if this is double buffered; defaults to false
937       */
938      public boolean isDoubleBuffered()
939      {
940        return false;
941      }
942    
943      /**
944       * Enables or disables input method support for this component. By default,
945       * components have this enabled. Input methods are given the opportunity
946       * to process key events before this component and its listeners.
947       *
948       * @param enable true to enable input method processing
949       * @see #processKeyEvent(KeyEvent)
950       * @since 1.2
951       */
952      public void enableInputMethods(boolean enable)
953      {
954        if (enable)
955          eventMask |= AWTEvent.INPUT_ENABLED_EVENT_MASK;
956        else
957          eventMask &= ~AWTEvent.INPUT_ENABLED_EVENT_MASK;
958      }
959    
960      /**
961       * Makes this component visible or invisible. Note that it wtill might
962       * not show the component, if a parent is invisible.
963       *
964       * @param visible true to make this component visible
965       * 
966       * @see #isVisible()
967       * 
968       * @since 1.1
969       */
970      public void setVisible(boolean visible)
971      {
972        // Inspection by subclassing shows that Sun's implementation calls
973        // show(boolean) which then calls show() or hide(). It is the show()
974        // method that is overriden in subclasses like Window.
975        show(visible);
976      }
977    
978      /**
979       * Makes this component visible on the screen.
980       *
981       * @deprecated use {@link #setVisible(boolean)} instead
982       */
983      public void show()
984      {
985        // We must set visible before showing the peer.  Otherwise the
986        // peer could post paint events before visible is true, in which
987        // case lightweight components are not initially painted --
988        // Container.paint first calls isShowing () before painting itself
989        // and its children.
990        if(! visible)
991          {
992            // Need to lock the tree here to avoid races and inconsistencies.
993            synchronized (getTreeLock())
994              {
995                visible = true;
996                // Avoid NullPointerExceptions by creating a local reference.
997                ComponentPeer currentPeer = peer;
998                if (currentPeer != null)
999                  {
1000                    currentPeer.show();
1001    
1002                    // Fire HierarchyEvent.
1003                    fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED,
1004                                       this, parent,
1005                                       HierarchyEvent.SHOWING_CHANGED);
1006    
1007                    // The JDK repaints the component before invalidating the parent.
1008                    // So do we.
1009                    if (peer instanceof LightweightPeer)
1010                      repaint();
1011                  }
1012    
1013                // Only post an event if this component actually has a listener
1014                // or has this event explicitly enabled.
1015                if (componentListener != null
1016                    || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0)
1017                  {
1018                    ComponentEvent ce =
1019                      new ComponentEvent(this,ComponentEvent.COMPONENT_SHOWN);
1020                    getToolkit().getSystemEventQueue().postEvent(ce);
1021                  }
1022              }
1023    
1024            // Invalidate the parent if we have one. The component itself must
1025            // not be invalidated. We also avoid NullPointerException with
1026            // a local reference here.
1027            Container currentParent = parent;
1028            if (currentParent != null)
1029              currentParent.invalidate();
1030    
1031          }
1032      }
1033    
1034      /**
1035       * Makes this component visible or invisible.
1036       *
1037       * @param visible true to make this component visible
1038       * 
1039       * @deprecated use {@link #setVisible(boolean)} instead
1040       */
1041      public void show(boolean visible)
1042      {
1043        if (visible)
1044          show();
1045        else
1046          hide();
1047      }
1048    
1049      /**
1050       * Hides this component so that it is no longer shown on the screen.
1051       *
1052       * @deprecated use {@link #setVisible(boolean)} instead
1053       */
1054      public void hide()
1055      {
1056        if (visible)
1057          {
1058            // Need to lock the tree here to avoid races and inconsistencies.
1059            synchronized (getTreeLock())
1060              {
1061                visible = false;
1062    
1063                // Avoid NullPointerExceptions by creating a local reference.
1064                ComponentPeer currentPeer = peer;
1065                if (currentPeer != null)
1066                  {
1067                    currentPeer.hide();
1068    
1069                    // Fire hierarchy event.
1070                    fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED,
1071                                       this, parent,
1072                                       HierarchyEvent.SHOWING_CHANGED);
1073                    // The JDK repaints the component before invalidating the
1074                    // parent. So do we. This only applies for lightweights.
1075                    if (peer instanceof LightweightPeer)
1076                      repaint();
1077                  }
1078    
1079                // Only post an event if this component actually has a listener
1080                // or has this event explicitly enabled.
1081                if (componentListener != null
1082                    || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0)
1083                  {
1084                    ComponentEvent ce =
1085                      new ComponentEvent(this,ComponentEvent.COMPONENT_HIDDEN);
1086                    getToolkit().getSystemEventQueue().postEvent(ce);
1087                  }
1088              }
1089    
1090            // Invalidate the parent if we have one. The component itself need
1091            // not be invalidated. We also avoid NullPointerException with
1092            // a local reference here.
1093            Container currentParent = parent;
1094            if (currentParent != null)
1095              currentParent.invalidate();
1096    
1097          }
1098      }
1099    
1100      /**
1101       * Returns this component's foreground color. If not set, this is inherited
1102       * from the parent.
1103       *
1104       * @return this component's foreground color, or null
1105       * @see #setForeground(Color)
1106       */
1107      public Color getForeground()
1108      {
1109        if (foreground != null)
1110          return foreground;
1111        return parent == null ? null : parent.getForeground();
1112      }
1113    
1114      /**
1115       * Sets this component's foreground color to the specified color. This is a
1116       * bound property.
1117       *
1118       * @param c the new foreground color
1119       * @see #getForeground()
1120       */
1121      public void setForeground(Color c)
1122      {
1123        if (peer != null)
1124          peer.setForeground(c);
1125        
1126        Color previous = foreground;
1127        foreground = c;
1128        firePropertyChange("foreground", previous, c);
1129      }
1130    
1131      /**
1132       * Tests if the foreground was explicitly set, or just inherited from the
1133       * parent.
1134       *
1135       * @return true if the foreground has been set
1136       * @since 1.4
1137       */
1138      public boolean isForegroundSet()
1139      {
1140        return foreground != null;
1141      }
1142    
1143      /**
1144       * Returns this component's background color. If not set, this is inherited
1145       * from the parent.
1146       *
1147       * @return the background color of the component, or null
1148       * @see #setBackground(Color)
1149       */
1150      public Color getBackground()
1151      {
1152        if (background != null)
1153          return background;
1154        return parent == null ? null : parent.getBackground();
1155      }
1156    
1157      /**
1158       * Sets this component's background color to the specified color. The parts
1159       * of the component affected by the background color may by system dependent.
1160       * This is a bound property.
1161       *
1162       * @param c the new background color
1163       * @see #getBackground()
1164       */
1165      public void setBackground(Color c)
1166      {
1167        // return if the background is already set to that color.
1168        if ((c != null) && c.equals(background))
1169          return;
1170    
1171        Color previous = background;
1172        background = c;
1173        if (peer != null && c != null)
1174          peer.setBackground(c);
1175        firePropertyChange("background", previous, c);
1176      }
1177    
1178      /**
1179       * Tests if the background was explicitly set, or just inherited from the
1180       * parent.
1181       *
1182       * @return true if the background has been set
1183       * @since 1.4
1184       */
1185      public boolean isBackgroundSet()
1186      {
1187        return background != null;
1188      }
1189    
1190      /**
1191       * Returns the font in use for this component. If not set, this is inherited
1192       * from the parent.
1193       *
1194       * @return the font for this component
1195       * @see #setFont(Font)
1196       */
1197      public Font getFont()
1198      {
1199        return getFontImpl();
1200      }
1201    
1202      /**
1203       * Implementation of getFont(). This is pulled out of getFont() to prevent
1204       * client programs from overriding this.
1205       *
1206       * @return the font of this component
1207       */
1208      private final Font getFontImpl()
1209      {
1210        Font f = font;
1211        if (f == null)
1212          {
1213            Component p = parent;
1214            if (p != null)
1215              f = p.getFontImpl();
1216            else
1217              {
1218                // It is important to return null here and not some kind of default
1219                // font, otherwise the Swing UI would not install its fonts because
1220                // it keeps non-UIResource fonts.
1221                f = null;
1222              }
1223          }
1224        return f;
1225      }
1226    
1227      /**
1228       * Sets the font for this component to the specified font. This is a bound
1229       * property.
1230       *
1231       * @param f the new font for this component
1232       * 
1233       * @see #getFont()
1234       */
1235      public void setFont(Font f)
1236      {
1237        Font oldFont;
1238        Font newFont;
1239        // Synchronize on the tree because getFontImpl() relies on the hierarchy
1240        // not beeing changed.
1241        synchronized (getTreeLock())
1242          {
1243            // Synchronize on this here to guarantee thread safety wrt to the
1244            // property values.
1245            synchronized (this)
1246              {
1247                oldFont = font;
1248                font = f;
1249                newFont = f;
1250              }
1251            // Create local variable here for thread safety.
1252            ComponentPeer p = peer;
1253            if (p != null)
1254              {
1255                // The peer receives the real font setting, which can depend on 
1256                // the parent font when this component's font has been set to null.
1257                f = getFont();
1258                if (f != null)
1259                  {
1260                    p.setFont(f);
1261                    peerFont = f;
1262                  }
1263              }
1264          }
1265    
1266        // Fire property change event.
1267        firePropertyChange("font", oldFont, newFont);
1268    
1269        // Invalidate when necessary as font changes can change the size of the
1270        // component.
1271        if (valid)
1272          invalidate();
1273      }
1274    
1275      /**
1276       * Tests if the font was explicitly set, or just inherited from the parent.
1277       *
1278       * @return true if the font has been set
1279       * @since 1.4
1280       */
1281      public boolean isFontSet()
1282      {
1283        return font != null;
1284      }
1285    
1286      /**
1287       * Returns the locale for this component. If this component does not
1288       * have a locale, the locale of the parent component is returned.
1289       *
1290       * @return the locale for this component
1291       * @throws IllegalComponentStateException if it has no locale or parent
1292       * @see #setLocale(Locale)
1293       * @since 1.1
1294       */
1295      public Locale getLocale()
1296      {
1297        if (locale != null)
1298          return locale;
1299        if (parent == null)
1300          throw new IllegalComponentStateException
1301            ("Component has no parent: can't determine Locale");
1302        return parent.getLocale();
1303      }
1304    
1305      /**
1306       * Sets the locale for this component to the specified locale. This is a
1307       * bound property.
1308       *
1309       * @param newLocale the new locale for this component
1310       */
1311      public void setLocale(Locale newLocale)
1312      {
1313        if (locale == newLocale)
1314          return;
1315    
1316        Locale oldLocale = locale;
1317        locale = newLocale;
1318        firePropertyChange("locale", oldLocale, newLocale);
1319        // New writing/layout direction or more/less room for localized labels.
1320        invalidate();
1321      }
1322    
1323      /**
1324       * Returns the color model of the device this componet is displayed on.
1325       *
1326       * @return this object's color model
1327       * @see Toolkit#getColorModel()
1328       */
1329      public ColorModel getColorModel()
1330      {
1331        GraphicsConfiguration config = getGraphicsConfiguration();
1332        return config != null ? config.getColorModel()
1333          : getToolkit().getColorModel();
1334      }
1335    
1336      /**
1337       * Returns the location of this component's top left corner relative to
1338       * its parent component. This may be outdated, so for synchronous behavior,
1339       * you should use a component listner.
1340       *
1341       * @return the location of this component
1342       * @see #setLocation(int, int)
1343       * @see #getLocationOnScreen()
1344       * @since 1.1
1345       */
1346      public Point getLocation()
1347      {
1348        return location ();
1349      }
1350    
1351      /**
1352       * Returns the location of this component's top left corner in screen
1353       * coordinates.
1354       *
1355       * @return the location of this component in screen coordinates
1356       * @throws IllegalComponentStateException if the component is not showing
1357       */
1358      public Point getLocationOnScreen()
1359      {
1360        if (! isShowing())
1361          throw new IllegalComponentStateException("component "
1362                                                   + getClass().getName()
1363                                                   + " not showing");
1364    
1365        // Need to lock the tree here. We get crazy races and explosions when
1366        // the tree changes while we are trying to find the location of this
1367        // component.
1368        synchronized (getTreeLock())
1369          {
1370            // Only a heavyweight peer can answer the question for the screen
1371            // location. So we are going through the hierarchy until we find
1372            // one and add up the offsets while doing so.
1373            int offsX = 0;
1374            int offsY = 0;
1375            ComponentPeer p = peer;
1376            Component comp = this;
1377            while (p instanceof LightweightPeer)
1378              {
1379                offsX += comp.x;
1380                offsY += comp.y;
1381                comp = comp.parent;
1382                p = comp == null ? null: comp.peer;
1383              }
1384            // Now we have a heavyweight component.
1385            assert ! (p instanceof LightweightPeer);
1386            Point loc = p.getLocationOnScreen();
1387            loc.x += offsX;
1388            loc.y += offsY;
1389            return loc;
1390          }
1391      }
1392    
1393      /**
1394       * Returns the location of this component's top left corner relative to
1395       * its parent component.
1396       *
1397       * @return the location of this component
1398       * @deprecated use {@link #getLocation()} instead
1399       */
1400      public Point location()
1401      {
1402        return new Point (x, y);
1403      }
1404    
1405      /**
1406       * Moves this component to the specified location, relative to the parent's
1407       * coordinates. The coordinates are the new upper left corner of this
1408       * component.
1409       *
1410       * @param x the new X coordinate of this component
1411       * @param y the new Y coordinate of this component
1412       * @see #getLocation()
1413       * @see #setBounds(int, int, int, int)
1414       */
1415      public void setLocation(int x, int y)
1416      {
1417        move (x, y);
1418      }
1419    
1420      /**
1421       * Moves this component to the specified location, relative to the parent's
1422       * coordinates. The coordinates are the new upper left corner of this
1423       * component.
1424       *
1425       * @param x the new X coordinate of this component
1426       * @param y the new Y coordinate of this component
1427       * @deprecated use {@link #setLocation(int, int)} instead
1428       */
1429      public void move(int x, int y)
1430      {
1431        setBounds(x, y, this.width, this.height);
1432      }
1433    
1434      /**
1435       * Moves this component to the specified location, relative to the parent's
1436       * coordinates. The coordinates are the new upper left corner of this
1437       * component.
1438       *
1439       * @param p new coordinates for this component
1440       * @throws NullPointerException if p is null
1441       * @see #getLocation()
1442       * @see #setBounds(int, int, int, int)
1443       * @since 1.1
1444       */
1445      public void setLocation(Point p)
1446      {
1447        setLocation(p.x, p.y);
1448      }
1449    
1450      /**
1451       * Returns the size of this object.
1452       *
1453       * @return the size of this object
1454       * @see #setSize(int, int)
1455       * @since 1.1
1456       */
1457      public Dimension getSize()
1458      {
1459        return size ();
1460      }
1461    
1462      /**
1463       * Returns the size of this object.
1464       *
1465       * @return the size of this object
1466       * @deprecated use {@link #getSize()} instead
1467       */
1468      public Dimension size()
1469      {
1470        return new Dimension (width, height);
1471      }
1472    
1473      /**
1474       * Sets the size of this component to the specified width and height.
1475       *
1476       * @param width the new width of this component
1477       * @param height the new height of this component
1478       * @see #getSize()
1479       * @see #setBounds(int, int, int, int)
1480       */
1481      public void setSize(int width, int height)
1482      {
1483        resize (width, height);
1484      }
1485    
1486      /**
1487       * Sets the size of this component to the specified value.
1488       *
1489       * @param width the new width of the component
1490       * @param height the new height of the component
1491       * @deprecated use {@link #setSize(int, int)} instead
1492       */
1493      public void resize(int width, int height)
1494      {
1495        setBounds(this.x, this.y, width, height);
1496      }
1497    
1498      /**
1499       * Sets the size of this component to the specified value.
1500       *
1501       * @param d the new size of this component
1502       * @throws NullPointerException if d is null
1503       * @see #setSize(int, int)
1504       * @see #setBounds(int, int, int, int)
1505       * @since 1.1
1506       */
1507      public void setSize(Dimension d)
1508      {
1509        resize (d);
1510      }
1511    
1512      /**
1513       * Sets the size of this component to the specified value.
1514       *
1515       * @param d the new size of this component
1516       * @throws NullPointerException if d is null
1517       * @deprecated use {@link #setSize(Dimension)} instead
1518       */
1519      public void resize(Dimension d)
1520      {
1521        resize (d.width, d.height);
1522      }
1523    
1524      /**
1525       * Returns a bounding rectangle for this component. Note that the
1526       * returned rectange is relative to this component's parent, not to
1527       * the screen.
1528       *
1529       * @return the bounding rectangle for this component
1530       * @see #setBounds(int, int, int, int)
1531       * @see #getLocation()
1532       * @see #getSize()
1533       */
1534      public Rectangle getBounds()
1535      {
1536        return bounds ();
1537      }
1538    
1539      /**
1540       * Returns a bounding rectangle for this component. Note that the
1541       * returned rectange is relative to this component's parent, not to
1542       * the screen.
1543       *
1544       * @return the bounding rectangle for this component
1545       * @deprecated use {@link #getBounds()} instead
1546       */
1547      public Rectangle bounds()
1548      {
1549        return new Rectangle (x, y, width, height);
1550      }
1551    
1552      /**
1553       * Sets the bounding rectangle for this component to the specified values.
1554       * Note that these coordinates are relative to the parent, not to the screen.
1555       *
1556       * @param x the X coordinate of the upper left corner of the rectangle
1557       * @param y the Y coordinate of the upper left corner of the rectangle
1558       * @param w the width of the rectangle
1559       * @param h the height of the rectangle
1560       * @see #getBounds()
1561       * @see #setLocation(int, int)
1562       * @see #setLocation(Point)
1563       * @see #setSize(int, int)
1564       * @see #setSize(Dimension)
1565       * @since 1.1
1566       */
1567      public void setBounds(int x, int y, int w, int h)
1568      {
1569        reshape (x, y, w, h);
1570      }
1571    
1572      /**
1573       * Sets the bounding rectangle for this component to the specified values.
1574       * Note that these coordinates are relative to the parent, not to the screen.
1575       *
1576       * @param x the X coordinate of the upper left corner of the rectangle
1577       * @param y the Y coordinate of the upper left corner of the rectangle
1578       * @param width the width of the rectangle
1579       * @param height the height of the rectangle
1580       * @deprecated use {@link #setBounds(int, int, int, int)} instead
1581       */
1582      public void reshape(int x, int y, int width, int height)
1583      {
1584        // We need to lock the tree here, otherwise we risk races and
1585        // inconsistencies.
1586        synchronized (getTreeLock())
1587          {
1588            int oldx = this.x;
1589            int oldy = this.y;
1590            int oldwidth = this.width;
1591            int oldheight = this.height;
1592        
1593            boolean resized = oldwidth != width || oldheight != height;
1594            boolean moved = oldx != x || oldy != y;
1595    
1596            if (resized || moved)
1597              {
1598                // Update the fields.
1599                this.x = x;
1600                this.y = y;
1601                this.width = width;
1602                this.height = height;
1603    
1604                if (peer != null)
1605                  {
1606                    peer.setBounds (x, y, width, height);
1607                    if (resized)
1608                      invalidate();
1609                    if (parent != null && parent.valid)
1610                      parent.invalidate();
1611                  }
1612    
1613                // Send some events to interested listeners.
1614                notifyReshape(resized, moved);
1615    
1616                // Repaint this component and the parent if appropriate.
1617                if (parent != null && peer instanceof LightweightPeer
1618                    && isShowing())
1619                  {
1620                    // The parent repaints the area that we occupied before.
1621                    parent.repaint(oldx, oldy, oldwidth, oldheight);
1622                    // This component repaints the area that we occupy now.
1623                    repaint();
1624                  }
1625              }
1626          }
1627      }
1628    
1629      /**
1630       * Sends notification to interested listeners about resizing and/or moving
1631       * the component. If this component has interested
1632       * component listeners or the corresponding event mask enabled, then
1633       * COMPONENT_MOVED and/or COMPONENT_RESIZED events are posted to the event
1634       * queue.
1635       *
1636       * @param resized true if the component has been resized, false otherwise
1637       * @param moved true if the component has been moved, false otherwise
1638       */
1639      void notifyReshape(boolean resized, boolean moved)
1640      {
1641        // Only post an event if this component actually has a listener
1642        // or has this event explicitly enabled.
1643        if (componentListener != null
1644            || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0)
1645          {
1646            // Fire component event on this component.
1647            if (moved)
1648              {
1649                ComponentEvent ce = new ComponentEvent(this,
1650                                                   ComponentEvent.COMPONENT_MOVED);
1651                getToolkit().getSystemEventQueue().postEvent(ce);
1652              }
1653            if (resized)
1654              {
1655                ComponentEvent ce = new ComponentEvent(this,
1656                                                 ComponentEvent.COMPONENT_RESIZED);
1657                getToolkit().getSystemEventQueue().postEvent(ce);
1658              }
1659          }
1660      }
1661    
1662      /**
1663       * Sets the bounding rectangle for this component to the specified
1664       * rectangle. Note that these coordinates are relative to the parent, not
1665       * to the screen.
1666       *
1667       * @param r the new bounding rectangle
1668       * @throws NullPointerException if r is null
1669       * @see #getBounds()
1670       * @see #setLocation(Point)
1671       * @see #setSize(Dimension)
1672       * @since 1.1
1673       */
1674      public void setBounds(Rectangle r)
1675      {
1676        setBounds (r.x, r.y, r.width, r.height);
1677      }
1678    
1679      /**
1680       * Gets the x coordinate of the upper left corner. This is more efficient
1681       * than getBounds().x or getLocation().x.
1682       *
1683       * @return the current x coordinate
1684       * @since 1.2
1685       */
1686      public int getX()
1687      {
1688        return x;
1689      }
1690    
1691      /**
1692       * Gets the y coordinate of the upper left corner. This is more efficient
1693       * than getBounds().y or getLocation().y.
1694       *
1695       * @return the current y coordinate
1696       * @since 1.2
1697       */
1698      public int getY()
1699      {
1700        return y;
1701      }
1702    
1703      /**
1704       * Gets the width of the component. This is more efficient than
1705       * getBounds().width or getSize().width.
1706       *
1707       * @return the current width
1708       * @since 1.2
1709       */
1710      public int getWidth()
1711      {
1712        return width;
1713      }
1714    
1715      /**
1716       * Gets the height of the component. This is more efficient than
1717       * getBounds().height or getSize().height.
1718       *
1719       * @return the current width
1720       * @since 1.2
1721       */
1722      public int getHeight()
1723      {
1724        return height;
1725      }
1726    
1727      /**
1728       * Returns the bounds of this component. This allows reuse of an existing
1729       * rectangle, if r is non-null.
1730       *
1731       * @param r the rectangle to use, or null
1732       * @return the bounds
1733       */
1734      public Rectangle getBounds(Rectangle r)
1735      {
1736        if (r == null)
1737          r = new Rectangle();
1738        r.x = x;
1739        r.y = y;
1740        r.width = width;
1741        r.height = height;
1742        return r;
1743      }
1744    
1745      /**
1746       * Returns the size of this component. This allows reuse of an existing
1747       * dimension, if d is non-null.
1748       *
1749       * @param d the dimension to use, or null
1750       * @return the size
1751       */
1752      public Dimension getSize(Dimension d)
1753      {
1754        if (d == null)
1755          d = new Dimension();
1756        d.width = width;
1757        d.height = height;
1758        return d;
1759      }
1760    
1761      /**
1762       * Returns the location of this component. This allows reuse of an existing
1763       * point, if p is non-null.
1764       *
1765       * @param p the point to use, or null
1766       * @return the location
1767       */
1768      public Point getLocation(Point p)
1769      {
1770        if (p == null)
1771          p = new Point();
1772        p.x = x;
1773        p.y = y;
1774        return p;
1775      }
1776    
1777      /**
1778       * Tests if this component is opaque. All "heavyweight" (natively-drawn)
1779       * components are opaque. A component is opaque if it draws all pixels in
1780       * the bounds; a lightweight component is partially transparent if it lets
1781       * pixels underneath show through. Subclasses that guarantee that all pixels
1782       * will be drawn should override this.
1783       *
1784       * @return true if this is opaque
1785       * @see #isLightweight()
1786       * @since 1.2
1787       */
1788      public boolean isOpaque()
1789      {
1790        return ! isLightweight();
1791      }
1792    
1793      /**
1794       * Return whether the component is lightweight. That means the component has
1795       * no native peer, but is displayable. This applies to subclasses of
1796       * Component not in this package, such as javax.swing.
1797       *
1798       * @return true if the component has a lightweight peer
1799       * @see #isDisplayable()
1800       * @since 1.2
1801       */
1802      public boolean isLightweight()
1803      {
1804        return peer instanceof LightweightPeer;
1805      }
1806    
1807      /**
1808       * Returns the component's preferred size.
1809       *
1810       * @return the component's preferred size
1811       * @see #getMinimumSize()
1812       * @see #setPreferredSize(Dimension)
1813       * @see LayoutManager
1814       */
1815      public Dimension getPreferredSize()
1816      {
1817        return preferredSize();
1818      }
1819    
1820      /**
1821       * Sets the preferred size that will be returned by 
1822       * {@link #getPreferredSize()} always, and sends a 
1823       * {@link PropertyChangeEvent} (with the property name 'preferredSize') to 
1824       * all registered listeners.
1825       * 
1826       * @param size  the preferred size (<code>null</code> permitted).
1827       * 
1828       * @since 1.5
1829       * 
1830       * @see #getPreferredSize()
1831       */
1832      public void setPreferredSize(Dimension size)
1833      {
1834        Dimension old = prefSizeSet ? prefSize : null;
1835        prefSize = size;
1836        prefSizeSet = (size != null);
1837        firePropertyChange("preferredSize", old, size);
1838      }
1839      
1840      /**
1841       * Returns <code>true</code> if the current preferred size is not 
1842       * <code>null</code> and was set by a call to 
1843       * {@link #setPreferredSize(Dimension)}, otherwise returns <code>false</code>.
1844       * 
1845       * @return A boolean.
1846       * 
1847       * @since 1.5
1848       */
1849      public boolean isPreferredSizeSet()
1850      {
1851        return prefSizeSet;
1852      }
1853      
1854      /**
1855       * Returns the component's preferred size.
1856       *
1857       * @return the component's preferred size
1858       * @deprecated use {@link #getPreferredSize()} instead
1859       */
1860      public Dimension preferredSize()
1861      {
1862        // Create a new Dimension object, so that the application doesn't mess
1863        // with the actual values.
1864        return new Dimension(preferredSizeImpl());
1865      }
1866    
1867      /**
1868       * The actual calculation is pulled out of preferredSize() so that
1869       * we can call it from Container.preferredSize() and avoid creating a
1870       * new intermediate Dimension object.
1871       * 
1872       * @return the preferredSize of the component
1873       */
1874      Dimension preferredSizeImpl()
1875      {
1876        Dimension size = prefSize;
1877        // Try to use a cached value.
1878        if (size == null || !(valid || prefSizeSet))
1879          {
1880            // We need to lock here, because the calculation depends on the
1881            // component structure not changing.
1882            synchronized (getTreeLock())
1883              {
1884                ComponentPeer p = peer;
1885                if (p != null)
1886                  size = peer.preferredSize();
1887                else
1888                  size = minimumSizeImpl();
1889              }
1890          }
1891        return size;
1892      }
1893    
1894      /**
1895       * Returns the component's minimum size.
1896       * 
1897       * @return the component's minimum size
1898       * @see #getPreferredSize()
1899       * @see #setMinimumSize(Dimension)
1900       * @see LayoutManager
1901       */
1902      public Dimension getMinimumSize()
1903      {
1904        return minimumSize();
1905      }
1906    
1907      /**
1908       * Sets the minimum size that will be returned by {@link #getMinimumSize()}
1909       * always, and sends a {@link PropertyChangeEvent} (with the property name
1910       * 'minimumSize') to all registered listeners.
1911       * 
1912       * @param size  the minimum size (<code>null</code> permitted).
1913       * 
1914       * @since 1.5
1915       * 
1916       * @see #getMinimumSize()
1917       */
1918      public void setMinimumSize(Dimension size)
1919      {
1920        Dimension old = minSizeSet ? minSize : null;
1921        minSize = size;
1922        minSizeSet = (size != null);
1923        firePropertyChange("minimumSize", old, size);
1924      }
1925      
1926      /**
1927       * Returns <code>true</code> if the current minimum size is not 
1928       * <code>null</code> and was set by a call to 
1929       * {@link #setMinimumSize(Dimension)}, otherwise returns <code>false</code>.
1930       * 
1931       * @return A boolean.
1932       * 
1933       * @since 1.5
1934       */
1935      public boolean isMinimumSizeSet()
1936      {
1937        return minSizeSet;
1938      }
1939      
1940      /**
1941       * Returns the component's minimum size.
1942       *
1943       * @return the component's minimum size
1944       * @deprecated use {@link #getMinimumSize()} instead
1945       */
1946      public Dimension minimumSize()
1947      {
1948        // Create a new Dimension object, so that the application doesn't mess
1949        // with the actual values.
1950        return new Dimension(minimumSizeImpl());
1951      }
1952    
1953      /**
1954       * The actual calculation is pulled out of minimumSize() so that
1955       * we can call it from Container.preferredSize() and
1956       * Component.preferredSizeImpl and avoid creating a
1957       * new intermediate Dimension object.
1958       * 
1959       * @return the minimum size of the component
1960       */
1961      Dimension minimumSizeImpl()
1962      {
1963        Dimension size = minSize;
1964        if (size == null || !(valid || minSizeSet))
1965          {
1966            // We need to lock here, because the calculation depends on the
1967            // component structure not changing.
1968            synchronized (getTreeLock())
1969              {
1970                ComponentPeer p = peer;
1971                if (p != null)
1972                  size = peer.minimumSize();
1973                else
1974                  size = size();
1975              }
1976          }
1977        return size;
1978      }
1979    
1980      /**
1981       * Returns the component's maximum size.
1982       *
1983       * @return the component's maximum size
1984       * @see #getMinimumSize()
1985       * @see #setMaximumSize(Dimension)
1986       * @see #getPreferredSize()
1987       * @see LayoutManager
1988       */
1989      public Dimension getMaximumSize()
1990      {
1991        return new Dimension(maximumSizeImpl());
1992      }
1993    
1994      /**
1995       * This is pulled out from getMaximumSize(), so that we can access it
1996       * from Container.getMaximumSize() without creating an additional
1997       * intermediate Dimension object.
1998       *
1999       * @return the maximum size of the component
2000       */
2001      Dimension maximumSizeImpl()
2002      {
2003        Dimension size;
2004        if (maxSizeSet)
2005          size = maxSize;
2006        else
2007          size = DEFAULT_MAX_SIZE;
2008        return size;
2009      }
2010    
2011      /**
2012       * Sets the maximum size that will be returned by {@link #getMaximumSize()}
2013       * always, and sends a {@link PropertyChangeEvent} (with the property name
2014       * 'maximumSize') to all registered listeners.
2015       * 
2016       * @param size  the maximum size (<code>null</code> permitted).
2017       * 
2018       * @since 1.5
2019       * 
2020       * @see #getMaximumSize()
2021       */
2022      public void setMaximumSize(Dimension size)
2023      {
2024        Dimension old = maxSizeSet ? maxSize : null;
2025        maxSize = size;
2026        maxSizeSet = (size != null);
2027        firePropertyChange("maximumSize", old, size);
2028      }
2029    
2030      /**
2031       * Returns <code>true</code> if the current maximum size is not 
2032       * <code>null</code> and was set by a call to 
2033       * {@link #setMaximumSize(Dimension)}, otherwise returns <code>false</code>.
2034       * 
2035       * @return A boolean.
2036       * 
2037       * @since 1.5
2038       */
2039      public boolean isMaximumSizeSet()
2040      {
2041        return maxSizeSet;
2042      }
2043      
2044      /**
2045       * Returns the preferred horizontal alignment of this component. The value
2046       * returned will be between {@link #LEFT_ALIGNMENT} and
2047       * {@link #RIGHT_ALIGNMENT}, inclusive.
2048       *
2049       * @return the preferred horizontal alignment of this component
2050       */
2051      public float getAlignmentX()
2052      {
2053        return CENTER_ALIGNMENT;
2054      }
2055    
2056      /**
2057       * Returns the preferred vertical alignment of this component. The value
2058       * returned will be between {@link #TOP_ALIGNMENT} and
2059       * {@link #BOTTOM_ALIGNMENT}, inclusive.
2060       *
2061       * @return the preferred vertical alignment of this component
2062       */
2063      public float getAlignmentY()
2064      {
2065        return CENTER_ALIGNMENT;
2066      }
2067    
2068      /**
2069       * Calls the layout manager to re-layout the component. This is called
2070       * during validation of a container in most cases.
2071       *
2072       * @see #validate()
2073       * @see LayoutManager
2074       */
2075      public void doLayout()
2076      {
2077        layout ();
2078      }
2079    
2080      /**
2081       * Calls the layout manager to re-layout the component. This is called
2082       * during validation of a container in most cases.
2083       *
2084       * @deprecated use {@link #doLayout()} instead
2085       */
2086      public void layout()
2087      {
2088        // Nothing to do unless we're a container.
2089      }
2090    
2091      /**
2092       * Called to ensure that the layout for this component is valid. This is
2093       * usually called on containers.
2094       *
2095       * @see #invalidate()
2096       * @see #doLayout()
2097       * @see LayoutManager
2098       * @see Container#validate()
2099       */
2100      public void validate()
2101      {
2102        if (! valid)
2103          {
2104            // Synchronize on the tree here as this might change the layout
2105            // of the hierarchy.
2106            synchronized (getTreeLock())
2107              {
2108                // Create local variables for thread safety.
2109                ComponentPeer p = peer;
2110                if (p != null)
2111                  {
2112                    // Possibly update the peer's font.
2113                    Font newFont = getFont();
2114                    Font oldFont = peerFont;
2115                    // Only update when the font really changed.
2116                    if (newFont != oldFont
2117                        && (oldFont == null || ! oldFont.equals(newFont)))
2118                      {
2119                        p.setFont(newFont);
2120                        peerFont = newFont;
2121                      }
2122                    // Let the peer perform any layout.
2123                    p.layout();
2124                  }
2125              }
2126            valid = true;
2127          }
2128      }
2129    
2130      /**
2131       * Invalidates this component and all of its parent components. This will
2132       * cause them to have their layout redone. This is called frequently, so
2133       * make it fast.
2134       */
2135      public void invalidate()
2136      {
2137        // Need to lock here, to avoid races and other ugly stuff when doing
2138        // layout or structure changes in other threads.
2139        synchronized (getTreeLock())
2140          {
2141            // Invalidate.
2142            valid = false;
2143    
2144            // Throw away cached layout information.
2145            if (! minSizeSet)
2146              minSize = null;
2147            if (! prefSizeSet)
2148              prefSize = null;
2149            if (! maxSizeSet)
2150              maxSize = null;
2151    
2152            // Also invalidate the parent, if it hasn't already been invalidated.
2153            if (parent != null && parent.isValid())
2154              parent.invalidate();
2155          }
2156      }
2157    
2158      /**
2159       * Returns a graphics object for this component. Returns <code>null</code>
2160       * if this component is not currently displayed on the screen.
2161       *
2162       * @return a graphics object for this component
2163       * @see #paint(Graphics)
2164       */
2165      public Graphics getGraphics()
2166      {
2167        // Only heavyweight peers can handle this.
2168        ComponentPeer p = peer;
2169        Graphics g = null;
2170        if (p instanceof LightweightPeer)
2171          {
2172            if (parent != null)
2173              {
2174                g = parent.getGraphics();
2175                if (g != null)
2176                  {
2177                    g.translate(x, y);
2178                    g.setClip(0, 0, width, height);
2179                    g.setFont(getFont());
2180                  }
2181              }
2182          }
2183        else
2184          {
2185            if (p != null)
2186              g = p.getGraphics();
2187          }
2188        return g;
2189      }
2190    
2191      /**
2192       * Returns the font metrics for the specified font in this component.
2193       *
2194       * @param font the font to retrieve metrics for
2195       * @return the font metrics for the specified font
2196       * @throws NullPointerException if font is null
2197       * @see #getFont()
2198       * @see Toolkit#getFontMetrics(Font)
2199       */
2200      public FontMetrics getFontMetrics(Font font)
2201      {
2202        ComponentPeer p = peer;
2203        Component comp = this;
2204        while (p instanceof LightweightPeer)
2205          {
2206            comp = comp.parent;
2207            p = comp == null ? null : comp.peer;
2208          }
2209    
2210        return p == null ? getToolkit().getFontMetrics(font)
2211               : p.getFontMetrics(font);
2212      }
2213    
2214      /**
2215       * Sets the cursor for this component to the specified cursor. The cursor
2216       * is displayed when the point is contained by the component, and the
2217       * component is visible, displayable, and enabled. This is inherited by
2218       * subcomponents unless they set their own cursor.
2219       *
2220       * @param cursor the new cursor for this component
2221       * @see #isEnabled()
2222       * @see #isShowing()
2223       * @see #getCursor()
2224       * @see #contains(int, int)
2225       * @see Toolkit#createCustomCursor(Image, Point, String)
2226       */
2227      public void setCursor(Cursor cursor)
2228      {
2229        this.cursor = cursor;
2230    
2231        // Only heavyweight peers handle this.
2232        ComponentPeer p = peer;
2233        Component comp = this;
2234        while (p instanceof LightweightPeer)
2235          {
2236            comp = comp.parent;
2237            p = comp == null ? null : comp.peer;
2238          }
2239    
2240        if (p != null)
2241          p.setCursor(cursor);
2242      }
2243    
2244      /**
2245       * Returns the cursor for this component. If not set, this is inherited
2246       * from the parent, or from Cursor.getDefaultCursor().
2247       *
2248       * @return the cursor for this component
2249       */
2250      public Cursor getCursor()
2251      {
2252        if (cursor != null)
2253          return cursor;
2254        return parent != null ? parent.getCursor() : Cursor.getDefaultCursor();
2255      }
2256    
2257      /**
2258       * Tests if the cursor was explicitly set, or just inherited from the parent.
2259       *
2260       * @return true if the cursor has been set
2261       * @since 1.4
2262       */
2263      public boolean isCursorSet()
2264      {
2265        return cursor != null;
2266      }
2267    
2268      /**
2269       * Paints this component on the screen. The clipping region in the graphics
2270       * context will indicate the region that requires painting. This is called
2271       * whenever the component first shows, or needs to be repaired because
2272       * something was temporarily drawn on top. It is not necessary for
2273       * subclasses to call <code>super.paint(g)</code>. Components with no area
2274       * are not painted.
2275       *
2276       * @param g the graphics context for this paint job
2277       * @see #update(Graphics)
2278       */
2279      public void paint(Graphics g)
2280      {
2281        // This is a callback method and is meant to be overridden by subclasses
2282        // that want to perform custom painting.
2283      }
2284    
2285      /**
2286       * Updates this component. This is called for heavyweight components in
2287       * response to {@link #repaint()}. The default implementation simply forwards
2288       * to {@link #paint(Graphics)}. The coordinates of the graphics are
2289       * relative to this component. Subclasses should call either
2290       * <code>super.update(g)</code> or <code>paint(g)</code>.
2291       *
2292       * @param g the graphics context for this update
2293       *
2294       * @see #paint(Graphics)
2295       * @see #repaint()
2296       */
2297      public void update(Graphics g)
2298      {
2299        // Note 1: We used to clear the background here for lightweights and
2300        // toplevel components. Tests show that this is not what the JDK does
2301        // here. Note that there is some special handling and background
2302        // clearing code in Container.update(Graphics).
2303    
2304        // Note 2 (for peer implementors): The JDK doesn't seem call update() for
2305        // toplevel components, even when an UPDATE event is sent (as a result
2306        // of repaint).
2307        paint(g);
2308      }
2309    
2310      /**
2311       * Paints this entire component, including any sub-components.
2312       *
2313       * @param g the graphics context for this paint job
2314       * 
2315       * @see #paint(Graphics)
2316       */
2317      public void paintAll(Graphics g)
2318      {
2319        if (isShowing())
2320          {
2321            validate();
2322            if (peer instanceof LightweightPeer)
2323              paint(g);
2324            else
2325              peer.paint(g);
2326          }
2327      }
2328    
2329      /**
2330       * Repaint this entire component. The <code>update()</code> method
2331       * on this component will be called as soon as possible.
2332       *
2333       * @see #update(Graphics)
2334       * @see #repaint(long, int, int, int, int)
2335       */
2336      public void repaint()
2337      {   
2338        repaint(0, 0, 0, width, height);
2339      }
2340    
2341      /**
2342       * Repaint this entire component. The <code>update()</code> method on this
2343       * component will be called in approximate the specified number of
2344       * milliseconds.
2345       *
2346       * @param tm milliseconds before this component should be repainted
2347       * @see #paint(Graphics)
2348       * @see #repaint(long, int, int, int, int)
2349       */
2350      public void repaint(long tm)
2351      {
2352        repaint(tm, 0, 0, width, height);
2353      }
2354    
2355      /**
2356       * Repaints the specified rectangular region within this component. The
2357       * <code>update</code> method on this component will be called as soon as
2358       * possible. The coordinates are relative to this component.
2359       *
2360       * @param x the X coordinate of the upper left of the region to repaint
2361       * @param y the Y coordinate of the upper left of the region to repaint
2362       * @param w the width of the region to repaint
2363       * @param h the height of the region to repaint
2364       * @see #update(Graphics)
2365       * @see #repaint(long, int, int, int, int)
2366       */
2367      public void repaint(int x, int y, int w, int h)
2368      {
2369        repaint(0, x, y, w, h);
2370      }
2371    
2372      /**
2373       * Repaints the specified rectangular region within this component. The
2374       * <code>update</code> method on this component will be called in
2375       * approximately the specified number of milliseconds. The coordinates
2376       * are relative to this component.
2377       *
2378       * @param tm milliseconds before this component should be repainted
2379       * @param x the X coordinate of the upper left of the region to repaint
2380       * @param y the Y coordinate of the upper left of the region to repaint
2381       * @param width the width of the region to repaint
2382       * @param height the height of the region to repaint
2383       * @see #update(Graphics)
2384       */
2385      public void repaint(long tm, int x, int y, int width, int height)
2386      {
2387        // The repaint() call has previously been delegated to
2388        // {@link ComponentPeer.repaint()}. Testing on the JDK using some
2389        // dummy peers show that this methods is never called. I think it makes
2390        // sense to actually perform the tasks below here, since it's pretty
2391        // much peer independent anyway, and makes sure only heavyweights are
2392        // bothered by this.
2393        ComponentPeer p = peer;
2394    
2395        // Let the nearest heavyweight parent handle repainting for lightweight
2396        // components.
2397        // We need to recursivly call repaint() on the parent here, since
2398        // a (lightweight) parent component might have overridden repaint()
2399        // to perform additional custom tasks.
2400    
2401        if (p instanceof LightweightPeer)
2402          {
2403            // We perform some boundary checking to restrict the paint
2404            // region to this component.
2405            if (parent != null)
2406              {
2407                int px = this.x + Math.max(0, x); 
2408                int py = this.y + Math.max(0, y);
2409                int pw = Math.min(this.width, width);
2410                int ph = Math.min(this.height, height);
2411                parent.repaint(tm, px, py, pw, ph);
2412              }
2413          }
2414        else
2415          {
2416            // Now send an UPDATE event to the heavyweight component that we've found.
2417            if (isVisible() && p != null && width > 0 && height > 0)
2418              {
2419                PaintEvent pe = new PaintEvent(this, PaintEvent.UPDATE,
2420                                               new Rectangle(x, y, width, height));
2421                getToolkit().getSystemEventQueue().postEvent(pe);
2422              }
2423          }
2424      }
2425    
2426      /**
2427       * Prints this component. This method is provided so that printing can be
2428       * done in a different manner from painting. However, the implementation
2429       * in this class simply calls the <code>paint()</code> method.
2430       *
2431       * @param g the graphics context of the print device
2432       * 
2433       * @see #paint(Graphics)
2434       */
2435      public void print(Graphics g)
2436      {
2437        paint(g);
2438      }
2439    
2440      /**
2441       * Prints this component, including all sub-components. 
2442       *
2443       * @param g the graphics context of the print device
2444       * 
2445       * @see #paintAll(Graphics)
2446       */
2447      public void printAll(Graphics g)
2448      {
2449        if( peer != null )
2450          peer.print( g );
2451        paintAll( g );
2452      }
2453    
2454      /**
2455       * Called when an image has changed so that this component is repainted.
2456       * This incrementally draws an image as more bits are available, when
2457       * possible. Incremental drawing is enabled if the system property
2458       * <code>awt.image.incrementalDraw</code> is not present or is true, in which
2459       * case the redraw rate is set to 100ms or the value of the system property
2460       * <code>awt.image.redrawrate</code>.
2461       *
2462       * <p>The coordinate system used depends on the particular flags.
2463       *
2464       * @param img the image that has been updated
2465       * @param flags tlags as specified in <code>ImageObserver</code>
2466       * @param x the X coordinate
2467       * @param y the Y coordinate
2468       * @param w the width
2469       * @param h the height
2470       * @return false if the image is completely loaded, loading has been
2471       * aborted, or an error has occurred.  true if more updates are
2472       * required.
2473       * @see ImageObserver
2474       * @see Graphics#drawImage(Image, int, int, Color, ImageObserver)
2475       * @see Graphics#drawImage(Image, int, int, ImageObserver)
2476       * @see Graphics#drawImage(Image, int, int, int, int, Color, ImageObserver)
2477       * @see Graphics#drawImage(Image, int, int, int, int, ImageObserver)
2478       * @see ImageObserver#imageUpdate(Image, int, int, int, int, int)
2479       */
2480      public boolean imageUpdate(Image img, int flags, int x, int y, int w, int h)
2481      {
2482        if ((flags & (FRAMEBITS | ALLBITS)) != 0)
2483          repaint();
2484        else if ((flags & SOMEBITS) != 0)
2485          {
2486            if (incrementalDraw)
2487              {
2488                if (redrawRate != null)
2489                  {
2490                    long tm = redrawRate.longValue();
2491                    if (tm < 0)
2492                      tm = 0;
2493                    repaint(tm);
2494                  }
2495                else
2496                  repaint(100);
2497              }
2498          }
2499        return (flags & (ALLBITS | ABORT | ERROR)) == 0;
2500      }
2501    
2502      /**
2503       * Creates an image from the specified producer.
2504       *
2505       * @param producer the image procedure to create the image from
2506       * @return the resulting image
2507       */
2508      public Image createImage(ImageProducer producer)
2509      {
2510        // Only heavyweight peers can handle this.
2511        ComponentPeer p = peer;
2512        Component comp = this;
2513        while (p instanceof LightweightPeer)
2514          {
2515            comp = comp.parent;
2516            p = comp == null ? null : comp.peer;
2517          }
2518    
2519        // Sun allows producer to be null.
2520        Image im;
2521        if (p != null)
2522          im = p.createImage(producer);
2523        else
2524          im = getToolkit().createImage(producer);
2525        return im;
2526      }
2527    
2528      /**
2529       * Creates an image with the specified width and height for use in
2530       * double buffering. Headless environments do not support images.
2531       *
2532       * @param width the width of the image
2533       * @param height the height of the image
2534       * @return the requested image, or null if it is not supported
2535       */
2536      public Image createImage (int width, int height)
2537      {
2538        Image returnValue = null;
2539        if (!GraphicsEnvironment.isHeadless ())
2540          {
2541            // Only heavyweight peers can handle this.
2542            ComponentPeer p = peer;
2543            Component comp = this;
2544            while (p instanceof LightweightPeer)
2545              {
2546                comp = comp.parent;
2547                p = comp == null ? null : comp.peer;
2548              }
2549    
2550            if (p != null)
2551              returnValue = p.createImage(width, height);
2552          }
2553        return returnValue;
2554      }
2555    
2556      /**
2557       * Creates an image with the specified width and height for use in
2558       * double buffering. Headless environments do not support images.
2559       *
2560       * @param width the width of the image
2561       * @param height the height of the image
2562       * @return the requested image, or null if it is not supported
2563       * @since 1.4
2564       */
2565      public VolatileImage createVolatileImage(int width, int height)
2566      {
2567        // Only heavyweight peers can handle this.
2568        ComponentPeer p = peer;
2569        Component comp = this;
2570        while (p instanceof LightweightPeer)
2571          {
2572            comp = comp.parent;
2573            p = comp == null ? null : comp.peer;
2574          }
2575    
2576        VolatileImage im = null;
2577        if (p != null)
2578          im = p.createVolatileImage(width, height);
2579        return im;
2580      }
2581    
2582      /**
2583       * Creates an image with the specified width and height for use in
2584       * double buffering. Headless environments do not support images. The image
2585       * will support the specified capabilities.
2586       *
2587       * @param width the width of the image
2588       * @param height the height of the image
2589       * @param caps the requested capabilities
2590       * @return the requested image, or null if it is not supported
2591       * @throws AWTException if a buffer with the capabilities cannot be created
2592       * @since 1.4
2593       */
2594      public VolatileImage createVolatileImage(int width, int height,
2595                                               ImageCapabilities caps)
2596        throws AWTException
2597      {
2598        // Only heavyweight peers can handle this.
2599        ComponentPeer p = peer;
2600        Component comp = this;
2601        while (p instanceof LightweightPeer)
2602          {
2603            comp = comp.parent;
2604            p = comp == null ? null : comp.peer;
2605          }
2606    
2607        VolatileImage im = null;
2608        if (p != null)
2609          im = peer.createVolatileImage(width, height);
2610        return im;
2611      }
2612    
2613      /**
2614       * Prepares the specified image for rendering on this component.
2615       *
2616       * @param image the image to prepare for rendering
2617       * @param observer the observer to notify of image preparation status
2618       * @return true if the image is already fully prepared
2619       * @throws NullPointerException if image is null
2620       */
2621      public boolean prepareImage(Image image, ImageObserver observer)
2622      {
2623        return prepareImage(image, image.getWidth(observer),
2624                            image.getHeight(observer), observer);
2625      }
2626    
2627      /**
2628       * Prepares the specified image for rendering on this component at the
2629       * specified scaled width and height
2630       *
2631       * @param image the image to prepare for rendering
2632       * @param width the scaled width of the image
2633       * @param height the scaled height of the image
2634       * @param observer the observer to notify of image preparation status
2635       * @return true if the image is already fully prepared
2636       */
2637      public boolean prepareImage(Image image, int width, int height,
2638                                  ImageObserver observer)
2639      {
2640        // Only heavyweight peers handle this.
2641        ComponentPeer p = peer;
2642        Component comp = this;
2643        while (p instanceof LightweightPeer)
2644          {
2645            comp = comp.parent;
2646            p = comp == null ? null : comp.peer;
2647          }
2648    
2649        boolean retval;
2650        if (p != null)
2651            retval = p.prepareImage(image, width, height, observer);
2652        else
2653            retval = getToolkit().prepareImage(image, width, height, observer);
2654        return retval;
2655      }
2656    
2657      /**
2658       * Returns the status of the loading of the specified image. The value
2659       * returned will be those flags defined in <code>ImageObserver</code>.
2660       *
2661       * @param image the image to check on
2662       * @param observer the observer to notify of image loading progress
2663       * @return the image observer flags indicating the status of the load
2664       * @see #prepareImage(Image, int, int, ImageObserver)
2665       * @see Toolkit#checkImage(Image, int, int, ImageObserver)
2666       * @throws NullPointerException if image is null
2667       */
2668      public int checkImage(Image image, ImageObserver observer)
2669      {
2670        return checkImage(image, -1, -1, observer);
2671      }
2672    
2673      /**
2674       * Returns the status of the loading of the specified image. The value
2675       * returned will be those flags defined in <code>ImageObserver</code>.
2676       *
2677       * @param image the image to check on
2678       * @param width the scaled image width
2679       * @param height the scaled image height
2680       * @param observer the observer to notify of image loading progress
2681       * @return the image observer flags indicating the status of the load
2682       * @see #prepareImage(Image, int, int, ImageObserver)
2683       * @see Toolkit#checkImage(Image, int, int, ImageObserver)
2684       */
2685      public int checkImage(Image image, int width, int height,
2686                            ImageObserver observer)
2687      {
2688        // Only heavyweight peers handle this.
2689        ComponentPeer p = peer;
2690        Component comp = this;
2691        while (p instanceof LightweightPeer)
2692          {
2693            comp = comp.parent;
2694            p = comp == null ? null : comp.peer;
2695          }
2696    
2697        int retval;
2698        if (p != null)
2699          retval = p.checkImage(image, width, height, observer);
2700        else
2701          retval = getToolkit().checkImage(image, width, height, observer);
2702        return retval;
2703      }
2704    
2705      /**
2706       * Sets whether paint messages delivered by the operating system should be
2707       * ignored. This does not affect messages from AWT, except for those
2708       * triggered by OS messages. Setting this to true can allow faster
2709       * performance in full-screen mode or page-flipping.
2710       *
2711       * @param ignoreRepaint the new setting for ignoring repaint events
2712       * @see #getIgnoreRepaint()
2713       * @see BufferStrategy
2714       * @see GraphicsDevice#setFullScreenWindow(Window)
2715       * @since 1.4
2716       */
2717      public void setIgnoreRepaint(boolean ignoreRepaint)
2718      {
2719        this.ignoreRepaint = ignoreRepaint;
2720      }
2721    
2722      /**
2723       * Test whether paint events from the operating system are ignored.
2724       *
2725       * @return the status of ignoring paint events
2726       * @see #setIgnoreRepaint(boolean)
2727       * @since 1.4
2728       */
2729      public boolean getIgnoreRepaint()
2730      {
2731        return ignoreRepaint;
2732      }
2733    
2734      /**
2735       * Tests whether or not the specified point is contained within this
2736       * component. Coordinates are relative to this component.
2737       *
2738       * @param x the X coordinate of the point to test
2739       * @param y the Y coordinate of the point to test
2740       * @return true if the point is within this component
2741       * @see #getComponentAt(int, int)
2742       */
2743      public boolean contains(int x, int y)
2744      {
2745        return inside (x, y);
2746      }
2747    
2748      /**
2749       * Tests whether or not the specified point is contained within this
2750       * component. Coordinates are relative to this component.
2751       *
2752       * @param x the X coordinate of the point to test
2753       * @param y the Y coordinate of the point to test
2754       * @return true if the point is within this component
2755       * @deprecated use {@link #contains(int, int)} instead
2756       */
2757      public boolean inside(int x, int y)
2758      {
2759        return x >= 0 && y >= 0 && x < width && y < height;
2760      }
2761    
2762      /**
2763       * Tests whether or not the specified point is contained within this
2764       * component. Coordinates are relative to this component.
2765       *
2766       * @param p the point to test
2767       * @return true if the point is within this component
2768       * @throws NullPointerException if p is null
2769       * @see #getComponentAt(Point)
2770       * @since 1.1
2771       */
2772      public boolean contains(Point p)
2773      {
2774        return contains (p.x, p.y);
2775      }
2776    
2777      /**
2778       * Returns the component occupying the position (x,y). This will either
2779       * be this component, an immediate child component, or <code>null</code>
2780       * if neither of the first two occupies the specified location.
2781       *
2782       * @param x the X coordinate to search for components at
2783       * @param y the Y coordinate to search for components at
2784       * @return the component at the specified location, or null
2785       * @see #contains(int, int)
2786       */
2787      public Component getComponentAt(int x, int y)
2788      {
2789        return locate (x, y);
2790      }
2791    
2792      /**
2793       * Returns the component occupying the position (x,y). This will either
2794       * be this component, an immediate child component, or <code>null</code>
2795       * if neither of the first two occupies the specified location.
2796       *
2797       * @param x the X coordinate to search for components at
2798       * @param y the Y coordinate to search for components at
2799       * @return the component at the specified location, or null
2800       * @deprecated use {@link #getComponentAt(int, int)} instead
2801       */
2802      public Component locate(int x, int y)
2803      {
2804        return contains (x, y) ? this : null;
2805      }
2806    
2807      /**
2808       * Returns the component occupying the position (x,y). This will either
2809       * be this component, an immediate child component, or <code>null</code>
2810       * if neither of the first two occupies the specified location.
2811       *
2812       * @param p the point to search for components at
2813       * @return the component at the specified location, or null
2814       * @throws NullPointerException if p is null
2815       * @see #contains(Point)
2816       * @since 1.1
2817       */
2818      public Component getComponentAt(Point p)
2819      {
2820        return getComponentAt (p.x, p.y);
2821      }
2822    
2823      /**
2824       * AWT 1.0 event delivery.
2825       *
2826       * Deliver an AWT 1.0 event to this Component.  This method simply
2827       * calls {@link #postEvent}.
2828       *
2829       * @param e the event to deliver
2830       * @deprecated use {@link #dispatchEvent (AWTEvent)} instead
2831       */
2832      public void deliverEvent (Event e)
2833      {
2834        postEvent (e);
2835      }
2836    
2837      /**
2838       * Forwards AWT events to processEvent() if:<ul>
2839       * <li>Events have been enabled for this type of event via
2840       * <code>enableEvents()</code></li>,
2841       * <li>There is at least one registered listener for this type of event</li>
2842       * </ul>
2843       *
2844       * @param e the event to dispatch
2845       */
2846      public final void dispatchEvent(AWTEvent e)
2847      {
2848        // Some subclasses in the AWT package need to override this behavior,
2849        // hence the use of dispatchEventImpl().
2850        dispatchEventImpl(e);
2851      }
2852    
2853      /**
2854       * By default, no old mouse events should be ignored.
2855       * This can be overridden by subclasses.
2856       * 
2857       * @return false, no mouse events are ignored.
2858       */
2859      static boolean ignoreOldMouseEvents()
2860      {
2861        return false;
2862      }
2863      
2864      /**
2865       * AWT 1.0 event handler.
2866       *
2867       * This method simply calls handleEvent and returns the result.
2868       *
2869       * @param e the event to handle
2870       * @return true if the event was handled, false otherwise
2871       * @deprecated use {@link #dispatchEvent(AWTEvent)} instead
2872       */
2873      public boolean postEvent (Event e)
2874      {
2875        boolean handled = handleEvent (e);
2876    
2877        if (!handled && getParent() != null)
2878          // FIXME: need to translate event coordinates to parent's
2879          // coordinate space.
2880          handled = getParent ().postEvent (e);
2881    
2882        return handled;
2883      }
2884    
2885      /**
2886       * Adds the specified listener to this component. This is harmless if the
2887       * listener is null, but if the listener has already been registered, it
2888       * will now be registered twice.
2889       *
2890       * @param listener the new listener to add
2891       * @see ComponentEvent
2892       * @see #removeComponentListener(ComponentListener)
2893       * @see #getComponentListeners()
2894       * @since 1.1
2895       */
2896      public synchronized void addComponentListener(ComponentListener listener)
2897      {
2898        if (listener != null)
2899          {
2900            componentListener = AWTEventMulticaster.add(componentListener,
2901                                                        listener);
2902            newEventsOnly = true;
2903          }
2904      }
2905    
2906      /**
2907       * Removes the specified listener from the component. This is harmless if
2908       * the listener was not previously registered.
2909       *
2910       * @param listener the listener to remove
2911       * @see ComponentEvent
2912       * @see #addComponentListener(ComponentListener)
2913       * @see #getComponentListeners()
2914       * @since 1.1
2915       */
2916      public synchronized void removeComponentListener(ComponentListener listener)
2917      {
2918        componentListener = AWTEventMulticaster.remove(componentListener, listener);
2919      }
2920    
2921      /**
2922       * Returns an array of all specified listeners registered on this component.
2923       *
2924       * @return an array of listeners
2925       * @see #addComponentListener(ComponentListener)
2926       * @see #removeComponentListener(ComponentListener)
2927       * @since 1.4
2928       */
2929      public synchronized ComponentListener[] getComponentListeners()
2930      {
2931        return (ComponentListener[])
2932          AWTEventMulticaster.getListeners(componentListener,
2933                                           ComponentListener.class);
2934      }
2935    
2936      /**
2937       * Adds the specified listener to this component. This is harmless if the
2938       * listener is null, but if the listener has already been registered, it
2939       * will now be registered twice.
2940       *
2941       * @param listener the new listener to add
2942       * @see FocusEvent
2943       * @see #removeFocusListener(FocusListener)
2944       * @see #getFocusListeners()
2945       * @since 1.1
2946       */
2947      public synchronized void addFocusListener(FocusListener listener)
2948      {
2949        if (listener != null)
2950          {
2951            focusListener = AWTEventMulticaster.add(focusListener, listener);
2952            newEventsOnly = true;
2953          }
2954      }
2955    
2956      /**
2957       * Removes the specified listener from the component. This is harmless if
2958       * the listener was not previously registered.
2959       *
2960       * @param listener the listener to remove
2961       * @see FocusEvent
2962       * @see #addFocusListener(FocusListener)
2963       * @see #getFocusListeners()
2964       * @since 1.1
2965       */
2966      public synchronized void removeFocusListener(FocusListener listener)
2967      {
2968        focusListener = AWTEventMulticaster.remove(focusListener, listener);
2969      }
2970    
2971      /**
2972       * Returns an array of all specified listeners registered on this component.
2973       *
2974       * @return an array of listeners
2975       * @see #addFocusListener(FocusListener)
2976       * @see #removeFocusListener(FocusListener)
2977       * @since 1.4
2978       */
2979      public synchronized FocusListener[] getFocusListeners()
2980      {
2981        return (FocusListener[])
2982          AWTEventMulticaster.getListeners(focusListener, FocusListener.class);
2983      }
2984    
2985      /**
2986       * Adds the specified listener to this component. This is harmless if the
2987       * listener is null, but if the listener has already been registered, it
2988       * will now be registered twice.
2989       *
2990       * @param listener the new listener to add
2991       * @see HierarchyEvent
2992       * @see #removeHierarchyListener(HierarchyListener)
2993       * @see #getHierarchyListeners()
2994       * @since 1.3
2995       */
2996      public synchronized void addHierarchyListener(HierarchyListener listener)
2997      {
2998        if (listener != null)
2999          {
3000            hierarchyListener = AWTEventMulticaster.add(hierarchyListener,
3001                                                        listener);
3002            newEventsOnly = true;
3003            // Need to lock the tree, otherwise we might end up inconsistent.
3004            synchronized (getTreeLock())
3005            {
3006              numHierarchyListeners++;
3007              if (parent != null)
3008                parent.updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK,
3009                                                    1);
3010            }
3011          }
3012      }
3013    
3014      /**
3015       * Removes the specified listener from the component. This is harmless if
3016       * the listener was not previously registered.
3017       *
3018       * @param listener the listener to remove
3019       * @see HierarchyEvent
3020       * @see #addHierarchyListener(HierarchyListener)
3021       * @see #getHierarchyListeners()
3022       * @since 1.3
3023       */
3024      public synchronized void removeHierarchyListener(HierarchyListener listener)
3025      {
3026        hierarchyListener = AWTEventMulticaster.remove(hierarchyListener, listener);
3027    
3028        // Need to lock the tree, otherwise we might end up inconsistent.
3029        synchronized (getTreeLock())
3030          {
3031            numHierarchyListeners--;
3032            if (parent != null)
3033              parent.updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK,
3034                                                  -1);
3035          }
3036      }
3037    
3038      /**
3039       * Returns an array of all specified listeners registered on this component.
3040       *
3041       * @return an array of listeners
3042       * @see #addHierarchyListener(HierarchyListener)
3043       * @see #removeHierarchyListener(HierarchyListener)
3044       * @since 1.4
3045       */
3046      public synchronized HierarchyListener[] getHierarchyListeners()
3047      {
3048        return (HierarchyListener[])
3049          AWTEventMulticaster.getListeners(hierarchyListener,
3050                                           HierarchyListener.class);
3051      }
3052    
3053      /**
3054       * Adds the specified listener to this component. This is harmless if the
3055       * listener is null, but if the listener has already been registered, it
3056       * will now be registered twice.
3057       *
3058       * @param listener the new listener to add
3059       * @see HierarchyEvent
3060       * @see #removeHierarchyBoundsListener(HierarchyBoundsListener)
3061       * @see #getHierarchyBoundsListeners()
3062       * @since 1.3
3063       */
3064      public synchronized void
3065        addHierarchyBoundsListener(HierarchyBoundsListener listener)
3066      {
3067        if (listener != null)
3068          {
3069            hierarchyBoundsListener =
3070              AWTEventMulticaster.add(hierarchyBoundsListener, listener);
3071            newEventsOnly = true;
3072    
3073            // Need to lock the tree, otherwise we might end up inconsistent.
3074            synchronized (getTreeLock())
3075            {
3076              numHierarchyBoundsListeners++;
3077              if (parent != null)
3078                parent.updateHierarchyListenerCount
3079                                         (AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, 1);
3080            }
3081          }
3082      }
3083    
3084      /**
3085       * Removes the specified listener from the component. This is harmless if
3086       * the listener was not previously registered.
3087       *
3088       * @param listener the listener to remove
3089       * @see HierarchyEvent
3090       * @see #addHierarchyBoundsListener(HierarchyBoundsListener)
3091       * @see #getHierarchyBoundsListeners()
3092       * @since 1.3
3093       */
3094      public synchronized void
3095        removeHierarchyBoundsListener(HierarchyBoundsListener listener)
3096      {
3097        hierarchyBoundsListener =
3098          AWTEventMulticaster.remove(hierarchyBoundsListener, listener);
3099    
3100        // Need to lock the tree, otherwise we might end up inconsistent.
3101        synchronized (getTreeLock())
3102          {
3103            numHierarchyBoundsListeners--;
3104            if (parent != null)
3105              parent.updateHierarchyListenerCount
3106                                             (AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
3107                                              -1);
3108          }
3109      }
3110    
3111      /**
3112       * Returns an array of all specified listeners registered on this component.
3113       *
3114       * @return an array of listeners
3115       * @see #addHierarchyBoundsListener(HierarchyBoundsListener)
3116       * @see #removeHierarchyBoundsListener(HierarchyBoundsListener)
3117       * @since 1.4
3118       */
3119      public synchronized HierarchyBoundsListener[] getHierarchyBoundsListeners()
3120      {
3121        return (HierarchyBoundsListener[])
3122          AWTEventMulticaster.getListeners(hierarchyBoundsListener,
3123                                           HierarchyBoundsListener.class);
3124      }
3125    
3126      /**
3127       * Fires a HierarchyEvent or HierarchyChangeEvent on this component.
3128       *
3129       * @param id the event id
3130       * @param changed the changed component
3131       * @param parent the parent
3132       * @param flags the event flags
3133       */
3134      void fireHierarchyEvent(int id, Component changed, Container parent,
3135                              long flags)
3136      {
3137        boolean enabled = false;
3138        switch (id)
3139        {
3140          case HierarchyEvent.HIERARCHY_CHANGED:
3141            enabled = hierarchyListener != null
3142                      || (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) != 0;
3143            break;
3144          case HierarchyEvent.ANCESTOR_MOVED:
3145          case HierarchyEvent.ANCESTOR_RESIZED:
3146            enabled = hierarchyBoundsListener != null
3147                      || (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0;
3148            break;
3149          default:
3150            assert false : "Should not reach here";
3151        }
3152        if (enabled)
3153          {
3154            HierarchyEvent ev = new HierarchyEvent(this, id, changed, parent,
3155                                                   flags);
3156            dispatchEvent(ev);
3157          }
3158      }
3159    
3160      /**
3161       * Adds the specified listener to this component. This is harmless if the
3162       * listener is null, but if the listener has already been registered, it
3163       * will now be registered twice.
3164       *
3165       * @param listener the new listener to add
3166       * @see KeyEvent
3167       * @see #removeKeyListener(KeyListener)
3168       * @see #getKeyListeners()
3169       * @since 1.1
3170       */
3171      public synchronized void addKeyListener(KeyListener listener)
3172      {
3173        if (listener != null)
3174          {
3175            keyListener = AWTEventMulticaster.add(keyListener, listener);
3176            newEventsOnly = true;
3177          }
3178      }
3179    
3180      /**
3181       * Removes the specified listener from the component. This is harmless if
3182       * the listener was not previously registered.
3183       *
3184       * @param listener the listener to remove
3185       * @see KeyEvent
3186       * @see #addKeyListener(KeyListener)
3187       * @see #getKeyListeners()
3188       * @since 1.1
3189       */
3190      public synchronized void removeKeyListener(KeyListener listener)
3191      {
3192        keyListener = AWTEventMulticaster.remove(keyListener, listener);
3193      }
3194    
3195      /**
3196       * Returns an array of all specified listeners registered on this component.
3197       *
3198       * @return an array of listeners
3199       * @see #addKeyListener(KeyListener)
3200       * @see #removeKeyListener(KeyListener)
3201       * @since 1.4
3202       */
3203      public synchronized KeyListener[] getKeyListeners()
3204      {
3205        return (KeyListener[])
3206          AWTEventMulticaster.getListeners(keyListener, KeyListener.class);
3207      }
3208    
3209      /**
3210       * Adds the specified listener to this component. This is harmless if the
3211       * listener is null, but if the listener has already been registered, it
3212       * will now be registered twice.
3213       *
3214       * @param listener the new listener to add
3215       * @see MouseEvent
3216       * @see #removeMouseListener(MouseListener)
3217       * @see #getMouseListeners()
3218       * @since 1.1
3219       */
3220      public synchronized void addMouseListener(MouseListener listener)
3221      {
3222        if (listener != null)
3223          {
3224            mouseListener = AWTEventMulticaster.add(mouseListener, listener);
3225            newEventsOnly = true;
3226          }
3227      }
3228    
3229      /**
3230       * Removes the specified listener from the component. This is harmless if
3231       * the listener was not previously registered.
3232       *
3233       * @param listener the listener to remove
3234       * @see MouseEvent
3235       * @see #addMouseListener(MouseListener)
3236       * @see #getMouseListeners()
3237       * @since 1.1
3238       */
3239      public synchronized void removeMouseListener(MouseListener listener)
3240      {
3241        mouseListener = AWTEventMulticaster.remove(mouseListener, listener);
3242      }
3243    
3244      /**
3245       * Returns an array of all specified listeners registered on this component.
3246       *
3247       * @return an array of listeners
3248       * @see #addMouseListener(MouseListener)
3249       * @see #removeMouseListener(MouseListener)
3250       * @since 1.4
3251       */
3252      public synchronized MouseListener[] getMouseListeners()
3253      {
3254        return (MouseListener[])
3255          AWTEventMulticaster.getListeners(mouseListener, MouseListener.class);
3256      }
3257    
3258      /**
3259       * Adds the specified listener to this component. This is harmless if the
3260       * listener is null, but if the listener has already been registered, it
3261       * will now be registered twice.
3262       *
3263       * @param listener the new listener to add
3264       * @see MouseEvent
3265       * @see #removeMouseMotionListener(MouseMotionListener)
3266       * @see #getMouseMotionListeners()
3267       * @since 1.1
3268       */
3269      public synchronized void addMouseMotionListener(MouseMotionListener listener)
3270      {
3271        if (listener != null)
3272          {
3273            mouseMotionListener = AWTEventMulticaster.add(mouseMotionListener,
3274                                                          listener);
3275            newEventsOnly = true;
3276          }
3277      }
3278    
3279      /**
3280       * Removes the specified listener from the component. This is harmless if
3281       * the listener was not previously registered.
3282       *
3283       * @param listener the listener to remove
3284       * @see MouseEvent
3285       * @see #addMouseMotionListener(MouseMotionListener)
3286       * @see #getMouseMotionListeners()
3287       * @since 1.1
3288       */
3289      public synchronized void removeMouseMotionListener(MouseMotionListener listener)
3290      {
3291        mouseMotionListener = AWTEventMulticaster.remove(mouseMotionListener, listener);
3292      }
3293    
3294      /**
3295       * Returns an array of all specified listeners registered on this component.
3296       *
3297       * @return an array of listeners
3298       * @see #addMouseMotionListener(MouseMotionListener)
3299       * @see #removeMouseMotionListener(MouseMotionListener)
3300       * @since 1.4
3301       */
3302      public synchronized MouseMotionListener[] getMouseMotionListeners()
3303      {
3304        return (MouseMotionListener[])
3305          AWTEventMulticaster.getListeners(mouseMotionListener,
3306                                           MouseMotionListener.class);
3307      }
3308    
3309      /**
3310       * Adds the specified listener to this component. This is harmless if the
3311       * listener is null, but if the listener has already been registered, it
3312       * will now be registered twice.
3313       *
3314       * @param listener the new listener to add
3315       * @see MouseEvent
3316       * @see MouseWheelEvent
3317       * @see #removeMouseWheelListener(MouseWheelListener)
3318       * @see #getMouseWheelListeners()
3319       * @since 1.4
3320       */
3321      public synchronized void addMouseWheelListener(MouseWheelListener listener)
3322      {
3323        if (listener != null)
3324          {
3325            mouseWheelListener = AWTEventMulticaster.add(mouseWheelListener,
3326                                                         listener);
3327            newEventsOnly = true;
3328          }
3329      }
3330    
3331      /**
3332       * Removes the specified listener from the component. This is harmless if
3333       * the listener was not previously registered.
3334       *
3335       * @param listener the listener to remove
3336       * @see MouseEvent
3337       * @see MouseWheelEvent
3338       * @see #addMouseWheelListener(MouseWheelListener)
3339       * @see #getMouseWheelListeners()
3340       * @since 1.4
3341       */
3342      public synchronized void removeMouseWheelListener(MouseWheelListener listener)
3343      {
3344        mouseWheelListener = AWTEventMulticaster.remove(mouseWheelListener, listener);
3345      }
3346    
3347      /**
3348       * Returns an array of all specified listeners registered on this component.
3349       *
3350       * @return an array of listeners
3351       * @see #addMouseWheelListener(MouseWheelListener)
3352       * @see #removeMouseWheelListener(MouseWheelListener)
3353       * @since 1.4
3354       */
3355      public synchronized MouseWheelListener[] getMouseWheelListeners()
3356      {
3357        return (MouseWheelListener[])
3358          AWTEventMulticaster.getListeners(mouseWheelListener,
3359                                           MouseWheelListener.class);
3360      }
3361    
3362      /**
3363       * Adds the specified listener to this component. This is harmless if the
3364       * listener is null, but if the listener has already been registered, it
3365       * will now be registered twice.
3366       *
3367       * @param listener the new listener to add
3368       * @see InputMethodEvent
3369       * @see #removeInputMethodListener(InputMethodListener)
3370       * @see #getInputMethodListeners()
3371       * @see #getInputMethodRequests()
3372       * @since 1.2
3373       */
3374      public synchronized void addInputMethodListener(InputMethodListener listener)
3375      {
3376        if (listener != null)
3377          {
3378            inputMethodListener = AWTEventMulticaster.add(inputMethodListener,
3379                                                          listener);
3380            newEventsOnly = true;
3381          }
3382      }
3383    
3384      /**
3385       * Removes the specified listener from the component. This is harmless if
3386       * the listener was not previously registered.
3387       *
3388       * @param listener the listener to remove
3389       * @see InputMethodEvent
3390       * @see #addInputMethodListener(InputMethodListener)
3391       * @see #getInputMethodRequests()
3392       * @since 1.2
3393       */
3394      public synchronized void removeInputMethodListener(InputMethodListener listener)
3395      {
3396        inputMethodListener = AWTEventMulticaster.remove(inputMethodListener, listener);
3397      }
3398    
3399      /**
3400       * Returns an array of all specified listeners registered on this component.
3401       *
3402       * @return an array of listeners
3403       * @see #addInputMethodListener(InputMethodListener)
3404       * @see #removeInputMethodListener(InputMethodListener)
3405       * @since 1.4
3406       */
3407      public synchronized InputMethodListener[] getInputMethodListeners()
3408      {
3409        return (InputMethodListener[])
3410          AWTEventMulticaster.getListeners(inputMethodListener,
3411                                           InputMethodListener.class);
3412      }
3413    
3414      /**
3415       * Returns all registered {@link EventListener}s of the given 
3416       * <code>listenerType</code>.
3417       *
3418       * @param listenerType the class of listeners to filter (<code>null</code> 
3419       *                     not permitted).
3420       *                     
3421       * @return An array of registered listeners.
3422       * 
3423       * @throws ClassCastException if <code>listenerType</code> does not implement
3424       *                            the {@link EventListener} interface.
3425       * @throws NullPointerException if <code>listenerType</code> is 
3426       *                              <code>null</code>.
3427       *                            
3428       * @see #getComponentListeners()
3429       * @see #getFocusListeners()
3430       * @see #getHierarchyListeners()
3431       * @see #getHierarchyBoundsListeners()
3432       * @see #getKeyListeners()
3433       * @see #getMouseListeners()
3434       * @see #getMouseMotionListeners()
3435       * @see #getMouseWheelListeners()
3436       * @see #getInputMethodListeners()
3437       * @see #getPropertyChangeListeners()
3438       * @since 1.3
3439       */
3440      public <T extends EventListener> T[] getListeners(Class<T> listenerType)
3441      {
3442        if (listenerType == ComponentListener.class)
3443          return (T[]) getComponentListeners();
3444        if (listenerType == FocusListener.class)
3445          return (T[]) getFocusListeners();
3446        if (listenerType == HierarchyListener.class)
3447          return (T[]) getHierarchyListeners();
3448        if (listenerType == HierarchyBoundsListener.class)
3449          return (T[]) getHierarchyBoundsListeners();
3450        if (listenerType == KeyListener.class)
3451          return (T[]) getKeyListeners();
3452        if (listenerType == MouseListener.class)
3453          return (T[]) getMouseListeners();
3454        if (listenerType == MouseMotionListener.class)
3455          return (T[]) getMouseMotionListeners();
3456        if (listenerType == MouseWheelListener.class)
3457          return (T[]) getMouseWheelListeners();
3458        if (listenerType == InputMethodListener.class)
3459          return (T[]) getInputMethodListeners();
3460        if (listenerType == PropertyChangeListener.class)
3461          return (T[]) getPropertyChangeListeners();
3462        return (T[]) Array.newInstance(listenerType, 0);
3463      }
3464    
3465      /**
3466       * Returns the input method request handler, for subclasses which support
3467       * on-the-spot text input. By default, input methods are handled by AWT,
3468       * and this returns null.
3469       *
3470       * @return the input method handler, null by default
3471       * @since 1.2
3472       */
3473      public InputMethodRequests getInputMethodRequests()
3474      {
3475        return null;
3476      }
3477    
3478      /**
3479       * Gets the input context of this component, which is inherited from the
3480       * parent unless this is overridden.
3481       *
3482       * @return the text input context
3483       * @since 1.2
3484       */
3485      public InputContext getInputContext()
3486      {
3487        return parent == null ? null : parent.getInputContext();
3488      }
3489    
3490      /**
3491       * Enables the specified events. The events to enable are specified
3492       * by OR-ing together the desired masks from <code>AWTEvent</code>.
3493       *
3494       * <p>Events are enabled by default when a listener is attached to the
3495       * component for that event type. This method can be used by subclasses
3496       * to ensure the delivery of a specified event regardless of whether
3497       * or not a listener is attached.
3498       *
3499       * @param eventsToEnable the desired events to enable
3500       * @see #processEvent(AWTEvent)
3501       * @see #disableEvents(long)
3502       * @see AWTEvent
3503       * @since 1.1
3504       */
3505      protected final void enableEvents(long eventsToEnable)
3506      {
3507        // Update the counter for hierarchy (bounds) listeners.
3508        if ((eventsToEnable & AWTEvent.HIERARCHY_EVENT_MASK) != 0
3509            && (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) == 0)
3510          {
3511            // Need to lock the tree, otherwise we might end up inconsistent.
3512            synchronized (getTreeLock())
3513              {
3514                numHierarchyListeners++;
3515                if (parent != null)
3516                  parent.updateHierarchyListenerCount
3517                                                    (AWTEvent.HIERARCHY_EVENT_MASK,
3518                                                     1);
3519              }
3520          }
3521        if ((eventsToEnable & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0
3522            && (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) == 0)
3523          {
3524            // Need to lock the tree, otherwise we might end up inconsistent.
3525            synchronized (getTreeLock())
3526              {
3527                numHierarchyBoundsListeners++;
3528                if (parent != null)
3529                  parent.updateHierarchyListenerCount
3530                                             (AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
3531                                              1);
3532              }
3533          }
3534    
3535        eventMask |= eventsToEnable;
3536        newEventsOnly = true;
3537    
3538        // Only heavyweight peers handle this.
3539        ComponentPeer p = peer;
3540        Component comp = this;
3541        while (p instanceof LightweightPeer)
3542          {
3543            comp = comp.parent;
3544            p = comp == null ? null : comp.peer;
3545          }
3546    
3547        if (p != null)
3548          p.setEventMask(eventMask);
3549    
3550      }
3551    
3552      /**
3553       * Disables the specified events. The events to disable are specified
3554       * by OR-ing together the desired masks from <code>AWTEvent</code>.
3555       *
3556       * @param eventsToDisable the desired events to disable
3557       * @see #enableEvents(long)
3558       * @since 1.1
3559       */
3560      protected final void disableEvents(long eventsToDisable)
3561      {
3562        // Update the counter for hierarchy (bounds) listeners.
3563        if ((eventsToDisable & AWTEvent.HIERARCHY_EVENT_MASK) != 0
3564            && (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) != 0)
3565          {
3566            // Need to lock the tree, otherwise we might end up inconsistent.
3567            synchronized (getTreeLock())
3568              {
3569                numHierarchyListeners--;
3570                if (parent != null)
3571                  parent.updateHierarchyListenerCount
3572                                                    (AWTEvent.HIERARCHY_EVENT_MASK,
3573                                                     -1);
3574              }
3575          }
3576        if ((eventsToDisable & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0
3577            && (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0)
3578          {
3579            // Need to lock the tree, otherwise we might end up inconsistent.
3580            synchronized (getTreeLock())
3581              {
3582                numHierarchyBoundsListeners--;
3583                if (parent != null)
3584                  parent.updateHierarchyListenerCount
3585                                             (AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
3586                                              -1);
3587              }
3588          }
3589    
3590        eventMask &= ~eventsToDisable;
3591    
3592        // Only heavyweight peers handle this.
3593        ComponentPeer p = peer;
3594        Component comp = this;
3595        while (p instanceof LightweightPeer)
3596          {
3597            comp = comp.parent;
3598            p = comp == null ? null : comp.peer;
3599          }
3600    
3601        if (p != null)
3602          p.setEventMask(eventMask);
3603    
3604      }
3605    
3606      /**
3607       * This is called by the EventQueue if two events with the same event id
3608       * and owner component are queued. Returns a new combined event, or null if
3609       * no combining is done. The coelesced events are currently mouse moves
3610       * (intermediate ones are discarded) and paint events (a merged paint is
3611       * created in place of the two events).
3612       *
3613       * @param existingEvent the event on the queue
3614       * @param newEvent the new event that might be entered on the queue
3615       * @return null if both events are kept, or the replacement coelesced event
3616       */
3617      protected AWTEvent coalesceEvents(AWTEvent existingEvent, AWTEvent newEvent)
3618      {
3619        AWTEvent coalesced = null;
3620        switch (existingEvent.id)
3621          {
3622          case MouseEvent.MOUSE_MOVED:
3623          case MouseEvent.MOUSE_DRAGGED:
3624            // Just drop the old (intermediate) event and return the new one.
3625            MouseEvent me1 = (MouseEvent) existingEvent;
3626            MouseEvent me2 = (MouseEvent) newEvent;
3627            if (me1.getModifiers() == me2.getModifiers())
3628              coalesced = newEvent;
3629            break;
3630          case PaintEvent.PAINT:
3631          case PaintEvent.UPDATE:
3632            // For heavyweights the EventQueue should ask the peer.
3633            if (peer == null || peer instanceof LightweightPeer)
3634              {
3635                PaintEvent pe1 = (PaintEvent) existingEvent;
3636                PaintEvent pe2 = (PaintEvent) newEvent;
3637                Rectangle r1 = pe1.getUpdateRect();
3638                Rectangle r2 = pe2.getUpdateRect();
3639                if (r1.contains(r2))
3640                  coalesced = existingEvent;
3641                else if (r2.contains(r1))
3642                  coalesced = newEvent;
3643              }
3644            else
3645              {
3646                // Replace the event and let the heavyweight figure out the expanding
3647                // of the repaint area.
3648                coalesced = newEvent;
3649              }
3650            break;
3651          default:
3652            coalesced = null;
3653          }
3654        return coalesced;
3655      }
3656    
3657      /**
3658       * Processes the specified event. In this class, this method simply
3659       * calls one of the more specific event handlers.
3660       *
3661       * @param e the event to process
3662       * @throws NullPointerException if e is null
3663       * @see #processComponentEvent(ComponentEvent)
3664       * @see #processFocusEvent(FocusEvent)
3665       * @see #processKeyEvent(KeyEvent)
3666       * @see #processMouseEvent(MouseEvent)
3667       * @see #processMouseMotionEvent(MouseEvent)
3668       * @see #processInputMethodEvent(InputMethodEvent)
3669       * @see #processHierarchyEvent(HierarchyEvent)
3670       * @see #processMouseWheelEvent(MouseWheelEvent)
3671       * @since 1.1
3672       */
3673      protected void processEvent(AWTEvent e)
3674      {
3675        /* Note: the order of these if statements are
3676           important. Subclasses must be checked first. Eg. MouseEvent
3677           must be checked before ComponentEvent, since a MouseEvent
3678           object is also an instance of a ComponentEvent. */
3679    
3680        if (e instanceof FocusEvent)
3681          processFocusEvent((FocusEvent) e);
3682        else if (e instanceof MouseWheelEvent)
3683          processMouseWheelEvent((MouseWheelEvent) e);
3684        else if (e instanceof MouseEvent)
3685          {
3686            if (e.id == MouseEvent.MOUSE_MOVED
3687                || e.id == MouseEvent.MOUSE_DRAGGED)
3688              processMouseMotionEvent((MouseEvent) e);
3689            else
3690              processMouseEvent((MouseEvent) e);
3691          }
3692        else if (e instanceof KeyEvent)
3693          processKeyEvent((KeyEvent) e);
3694        else if (e instanceof InputMethodEvent)
3695          processInputMethodEvent((InputMethodEvent) e);
3696        else if (e instanceof ComponentEvent)
3697          processComponentEvent((ComponentEvent) e);
3698        else if (e instanceof HierarchyEvent)
3699          {
3700            if (e.id == HierarchyEvent.HIERARCHY_CHANGED)
3701              processHierarchyEvent((HierarchyEvent) e);
3702            else
3703              processHierarchyBoundsEvent((HierarchyEvent) e);
3704          }
3705      }
3706    
3707      /**
3708       * Called when a component event is dispatched and component events are
3709       * enabled. This method passes the event along to any listeners
3710       * that are attached.
3711       *
3712       * @param e the <code>ComponentEvent</code> to process
3713       * @throws NullPointerException if e is null
3714       * @see ComponentListener
3715       * @see #addComponentListener(ComponentListener)
3716       * @see #enableEvents(long)
3717       * @since 1.1
3718       */
3719      protected void processComponentEvent(ComponentEvent e)
3720      {
3721        if (componentListener == null)
3722          return;
3723        switch (e.id)
3724          {
3725          case ComponentEvent.COMPONENT_HIDDEN:
3726            componentListener.componentHidden(e);
3727            break;
3728          case ComponentEvent.COMPONENT_MOVED:
3729            componentListener.componentMoved(e);
3730            break;
3731          case ComponentEvent.COMPONENT_RESIZED:
3732            componentListener.componentResized(e);
3733            break;
3734          case ComponentEvent.COMPONENT_SHOWN:
3735            componentListener.componentShown(e);
3736            break;
3737          }
3738      }
3739    
3740      /**
3741       * Called when a focus event is dispatched and component events are
3742       * enabled. This method passes the event along to any listeners
3743       * that are attached.
3744       *
3745       * @param e the <code>FocusEvent</code> to process
3746       * @throws NullPointerException if e is null
3747       * @see FocusListener
3748       * @see #addFocusListener(FocusListener)
3749       * @see #enableEvents(long)
3750       * @since 1.1
3751       */
3752      protected void processFocusEvent(FocusEvent e)
3753      {
3754        if (focusListener == null)
3755          return;
3756    
3757        switch (e.id)
3758          {
3759            case FocusEvent.FOCUS_GAINED:
3760              focusListener.focusGained(e);
3761            break;
3762            case FocusEvent.FOCUS_LOST:
3763              focusListener.focusLost(e);
3764            break;
3765          }
3766      }
3767    
3768      /**
3769       * Called when a key event is dispatched and component events are
3770       * enabled. This method passes the event along to any listeners
3771       * that are attached.
3772       *
3773       * @param e the <code>KeyEvent</code> to process
3774       * @throws NullPointerException if e is null
3775       * @see KeyListener
3776       * @see #addKeyListener(KeyListener)
3777       * @see #enableEvents(long)
3778       * @since 1.1
3779       */
3780      protected void processKeyEvent(KeyEvent e)
3781      {
3782        if (keyListener == null)
3783          return;
3784        switch (e.id)
3785          {
3786            case KeyEvent.KEY_PRESSED:
3787              keyListener.keyPressed(e);
3788            break;
3789            case KeyEvent.KEY_RELEASED:
3790              keyListener.keyReleased(e);
3791            break;
3792            case KeyEvent.KEY_TYPED:
3793              keyListener.keyTyped(e);
3794            break;
3795          }
3796      }
3797    
3798      /**
3799       * Called when a regular mouse event is dispatched and component events are
3800       * enabled. This method passes the event along to any listeners
3801       * that are attached.
3802       *
3803       * @param e the <code>MouseEvent</code> to process
3804       * @throws NullPointerException if e is null
3805       * @see MouseListener
3806       * @see #addMouseListener(MouseListener)
3807       * @see #enableEvents(long)
3808       * @since 1.1
3809       */
3810      protected void processMouseEvent(MouseEvent e)
3811      {
3812        if (mouseListener == null)
3813          return;
3814        switch (e.id)
3815          {
3816            case MouseEvent.MOUSE_CLICKED:
3817              mouseListener.mouseClicked(e);
3818            break;
3819            case MouseEvent.MOUSE_ENTERED:
3820              if( isLightweight() )
3821                setCursor( getCursor() );
3822              mouseListener.mouseEntered(e);
3823            break;
3824            case MouseEvent.MOUSE_EXITED:
3825              mouseListener.mouseExited(e);
3826            break;
3827            case MouseEvent.MOUSE_PRESSED:
3828              mouseListener.mousePressed(e);
3829            break;
3830            case MouseEvent.MOUSE_RELEASED:
3831              mouseListener.mouseReleased(e);
3832            break;
3833          }
3834      }
3835    
3836      /**
3837       * Called when a mouse motion event is dispatched and component events are
3838       * enabled. This method passes the event along to any listeners
3839       * that are attached.
3840       *
3841       * @param e the <code>MouseMotionEvent</code> to process
3842       * @throws NullPointerException if e is null
3843       * @see MouseMotionListener
3844       * @see #addMouseMotionListener(MouseMotionListener)
3845       * @see #enableEvents(long)
3846       * @since 1.1
3847       */
3848      protected void processMouseMotionEvent(MouseEvent e)
3849      {
3850        if (mouseMotionListener == null)
3851          return;
3852        switch (e.id)
3853          {
3854            case MouseEvent.MOUSE_DRAGGED:
3855              mouseMotionListener.mouseDragged(e);
3856            break;
3857            case MouseEvent.MOUSE_MOVED:
3858              mouseMotionListener.mouseMoved(e);
3859            break;
3860          }
3861          e.consume();
3862      }
3863    
3864      /**
3865       * Called when a mouse wheel event is dispatched and component events are
3866       * enabled. This method passes the event along to any listeners that are
3867       * attached.
3868       *
3869       * @param e the <code>MouseWheelEvent</code> to process
3870       * @throws NullPointerException if e is null
3871       * @see MouseWheelListener
3872       * @see #addMouseWheelListener(MouseWheelListener)
3873       * @see #enableEvents(long)
3874       * @since 1.4
3875       */
3876      protected void processMouseWheelEvent(MouseWheelEvent e)
3877      {
3878        if (mouseWheelListener != null
3879            && e.id == MouseEvent.MOUSE_WHEEL)
3880        {
3881          mouseWheelListener.mouseWheelMoved(e);
3882          e.consume();
3883        }   
3884      }
3885    
3886      /**
3887       * Called when an input method event is dispatched and component events are
3888       * enabled. This method passes the event along to any listeners that are
3889       * attached.
3890       *
3891       * @param e the <code>InputMethodEvent</code> to process
3892       * @throws NullPointerException if e is null
3893       * @see InputMethodListener
3894       * @see #addInputMethodListener(InputMethodListener)
3895       * @see #enableEvents(long)
3896       * @since 1.2
3897       */
3898      protected void processInputMethodEvent(InputMethodEvent e)
3899      {
3900        if (inputMethodListener == null)
3901          return;
3902        switch (e.id)
3903          {
3904            case InputMethodEvent.CARET_POSITION_CHANGED:
3905              inputMethodListener.caretPositionChanged(e);
3906            break;
3907            case InputMethodEvent.INPUT_METHOD_TEXT_CHANGED:
3908              inputMethodListener.inputMethodTextChanged(e);
3909            break;
3910          }
3911      }
3912    
3913      /**
3914       * Called when a hierarchy change event is dispatched and component events
3915       * are enabled. This method passes the event along to any listeners that are
3916       * attached.
3917       *
3918       * @param e the <code>HierarchyEvent</code> to process
3919       * @throws NullPointerException if e is null
3920       * @see HierarchyListener
3921       * @see #addHierarchyListener(HierarchyListener)
3922       * @see #enableEvents(long)
3923       * @since 1.3
3924       */
3925      protected void processHierarchyEvent(HierarchyEvent e)
3926      {
3927        if (hierarchyListener == null)
3928          return;
3929        if (e.id == HierarchyEvent.HIERARCHY_CHANGED)
3930          hierarchyListener.hierarchyChanged(e);
3931      }
3932    
3933      /**
3934       * Called when a hierarchy bounds event is dispatched and component events
3935       * are enabled. This method passes the event along to any listeners that are
3936       * attached.
3937       *
3938       * @param e the <code>HierarchyEvent</code> to process
3939       * @throws NullPointerException if e is null
3940       * @see HierarchyBoundsListener
3941       * @see #addHierarchyBoundsListener(HierarchyBoundsListener)
3942       * @see #enableEvents(long)
3943       * @since 1.3
3944       */
3945      protected void processHierarchyBoundsEvent(HierarchyEvent e)
3946      {
3947        if (hierarchyBoundsListener == null)
3948          return;
3949        switch (e.id)
3950          {
3951            case HierarchyEvent.ANCESTOR_MOVED:
3952              hierarchyBoundsListener.ancestorMoved(e);
3953            break;
3954            case HierarchyEvent.ANCESTOR_RESIZED:
3955              hierarchyBoundsListener.ancestorResized(e);
3956            break;
3957          }
3958      }
3959    
3960      /**
3961       * AWT 1.0 event handler.
3962       *
3963       * This method calls one of the event-specific handler methods.  For
3964       * example for key events, either {@link #keyDown(Event,int)}
3965       * or {@link #keyUp(Event,int)} is called.  A derived
3966       * component can override one of these event-specific methods if it
3967       * only needs to handle certain event types.  Otherwise it can
3968       * override handleEvent itself and handle any event.
3969       *
3970       * @param evt the event to handle
3971       * @return true if the event was handled, false otherwise
3972       * @deprecated use {@link #processEvent(AWTEvent)} instead
3973       */
3974      public boolean handleEvent (Event evt)
3975      {
3976        switch (evt.id)
3977          {
3978            // Handle key events.
3979          case Event.KEY_ACTION:
3980          case Event.KEY_PRESS:
3981            return keyDown (evt, evt.key);
3982          case Event.KEY_ACTION_RELEASE:
3983          case Event.KEY_RELEASE:
3984            return keyUp (evt, evt.key);
3985    
3986            // Handle mouse events.
3987          case Event.MOUSE_DOWN:
3988            return mouseDown (evt, evt.x, evt.y);
3989          case Event.MOUSE_UP:
3990            return mouseUp (evt, evt.x, evt.y);
3991          case Event.MOUSE_MOVE:
3992            return mouseMove (evt, evt.x, evt.y);
3993          case Event.MOUSE_DRAG:
3994            return mouseDrag (evt, evt.x, evt.y);
3995          case Event.MOUSE_ENTER:
3996            return mouseEnter (evt, evt.x, evt.y);
3997          case Event.MOUSE_EXIT:
3998            return mouseExit (evt, evt.x, evt.y);
3999    
4000            // Handle focus events.
4001          case Event.GOT_FOCUS:
4002            return gotFocus (evt, evt.arg);
4003          case Event.LOST_FOCUS:
4004            return lostFocus (evt, evt.arg);
4005    
4006            // Handle action event.
4007          case Event.ACTION_EVENT:
4008            return action (evt, evt.arg);
4009          }
4010        // Unknown event.
4011        return false;
4012      }
4013    
4014      /**
4015       * AWT 1.0 MOUSE_DOWN event handler.  This method is meant to be
4016       * overridden by components providing their own MOUSE_DOWN handler.
4017       * The default implementation simply returns false.
4018       *
4019       * @param evt the event to handle
4020       * @param x the x coordinate, ignored
4021       * @param y the y coordinate, ignored
4022       * @return false
4023       * @deprecated use {@link #processMouseEvent(MouseEvent)} instead
4024       */
4025      public boolean mouseDown(Event evt, int x, int y)
4026      {
4027        return false;
4028      }
4029    
4030      /**
4031       * AWT 1.0 MOUSE_DRAG event handler.  This method is meant to be
4032       * overridden by components providing their own MOUSE_DRAG handler.
4033       * The default implementation simply returns false.
4034       *
4035       * @param evt the event to handle
4036       * @param x the x coordinate, ignored
4037       * @param y the y coordinate, ignored
4038       * @return false
4039       * @deprecated use {@link #processMouseMotionEvent(MouseEvent)} instead
4040       */
4041      public boolean mouseDrag(Event evt, int x, int y)
4042      {
4043        return false;
4044      }
4045    
4046      /**
4047       * AWT 1.0 MOUSE_UP event handler.  This method is meant to be
4048       * overridden by components providing their own MOUSE_UP handler.
4049       * The default implementation simply returns false.
4050       *
4051       * @param evt the event to handle
4052       * @param x the x coordinate, ignored
4053       * @param y the y coordinate, ignored
4054       * @return false
4055       * @deprecated use {@link #processMouseEvent(MouseEvent)} instead
4056       */
4057      public boolean mouseUp(Event evt, int x, int y)
4058      {
4059        return false;
4060      }
4061    
4062      /**
4063       * AWT 1.0 MOUSE_MOVE event handler.  This method is meant to be
4064       * overridden by components providing their own MOUSE_MOVE handler.
4065       * The default implementation simply returns false.
4066       *
4067       * @param evt the event to handle
4068       * @param x the x coordinate, ignored
4069       * @param y the y coordinate, ignored
4070       * @return false
4071       * @deprecated use {@link #processMouseMotionEvent(MouseEvent)} instead
4072       */
4073      public boolean mouseMove(Event evt, int x, int y)
4074      {
4075        return false;
4076      }
4077    
4078      /**
4079       * AWT 1.0 MOUSE_ENTER event handler.  This method is meant to be
4080       * overridden by components providing their own MOUSE_ENTER handler.
4081       * The default implementation simply returns false.
4082       *
4083       * @param evt the event to handle
4084       * @param x the x coordinate, ignored
4085       * @param y the y coordinate, ignored
4086       * @return false
4087       * @deprecated use {@link #processMouseEvent(MouseEvent)} instead
4088       */
4089      public boolean mouseEnter(Event evt, int x, int y)
4090      {
4091        return false;
4092      }
4093    
4094      /**
4095       * AWT 1.0 MOUSE_EXIT event handler.  This method is meant to be
4096       * overridden by components providing their own MOUSE_EXIT handler.
4097       * The default implementation simply returns false.
4098       *
4099       * @param evt the event to handle
4100       * @param x the x coordinate, ignored
4101       * @param y the y coordinate, ignored
4102       * @return false
4103       * @deprecated use {@link #processMouseEvent(MouseEvent)} instead
4104       */
4105      public boolean mouseExit(Event evt, int x, int y)
4106      {
4107        return false;
4108      }
4109    
4110      /**
4111       * AWT 1.0 KEY_PRESS and KEY_ACTION event handler.  This method is
4112       * meant to be overridden by components providing their own key
4113       * press handler.  The default implementation simply returns false.
4114       *
4115       * @param evt the event to handle
4116       * @param key the key pressed, ignored
4117       * @return false
4118       * @deprecated use {@link #processKeyEvent(KeyEvent)} instead
4119       */
4120      public boolean keyDown(Event evt, int key)
4121      {
4122        return false;
4123      }
4124    
4125      /**
4126       * AWT 1.0 KEY_RELEASE and KEY_ACTION_RELEASE event handler.  This
4127       * method is meant to be overridden by components providing their
4128       * own key release handler.  The default implementation simply
4129       * returns false.
4130       *
4131       * @param evt the event to handle
4132       * @param key the key pressed, ignored
4133       * @return false
4134       * @deprecated use {@link #processKeyEvent(KeyEvent)} instead
4135       */
4136      public boolean keyUp(Event evt, int key)
4137      {
4138        return false;
4139      }
4140    
4141      /**
4142       * AWT 1.0 ACTION_EVENT event handler.  This method is meant to be
4143       * overridden by components providing their own action event
4144       * handler.  The default implementation simply returns false.
4145       *
4146       * @param evt the event to handle
4147       * @param what the object acted on, ignored
4148       * @return false
4149       * @deprecated in classes which support actions, use
4150       *             <code>processActionEvent(ActionEvent)</code> instead
4151       */
4152      public boolean action(Event evt, Object what)
4153      {
4154        return false;
4155      }
4156    
4157      /**
4158       * Called when the parent of this Component is made visible or when
4159       * the Component is added to an already visible Container and needs
4160       * to be shown.  A native peer - if any - is created at this
4161       * time. This method is called automatically by the AWT system and
4162       * should not be called by user level code.
4163       *
4164       * @see #isDisplayable()
4165       * @see #removeNotify()
4166       */
4167      public void addNotify()
4168      {
4169        // We need to lock the tree here to avoid races and inconsistencies.
4170        synchronized (getTreeLock())
4171          {
4172            if (peer == null)
4173              peer = getToolkit().createComponent(this);
4174            else if (parent != null && parent.isLightweight())
4175              new HeavyweightInLightweightListener(parent);
4176            // Now that all the children has gotten their peers, we should
4177            // have the event mask needed for this component and its
4178            //lightweight subcomponents.
4179            peer.setEventMask(eventMask);
4180    
4181            // We used to leave the invalidate() to the peer. However, I put it
4182            // back here for 2 reasons: 1) The RI does call invalidate() from
4183            // addNotify(); 2) The peer shouldn't be bother with validation too
4184            // much.
4185            invalidate();
4186    
4187            if (dropTarget != null) 
4188              dropTarget.addNotify(peer);
4189    
4190            // Fetch the peerFont for later installation in validate().
4191            peerFont = getFont();
4192    
4193            // Notify hierarchy listeners.
4194            long flags = HierarchyEvent.DISPLAYABILITY_CHANGED;
4195            if (isHierarchyVisible())
4196              flags |= HierarchyEvent.SHOWING_CHANGED;
4197            fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, this, parent,
4198                               flags);
4199          }
4200      }
4201    
4202      /**
4203       * Called to inform this component is has been removed from its
4204       * container. Its native peer - if any - is destroyed at this time.
4205       * This method is called automatically by the AWT system and should
4206       * not be called by user level code.
4207       *
4208       * @see #isDisplayable()
4209       * @see #addNotify()
4210       */
4211      public void removeNotify()
4212      {
4213        // We need to lock the tree here to avoid races and inconsistencies.
4214        synchronized (getTreeLock())
4215          {
4216            // We null our peer field before disposing of it, such that if we're
4217            // not the event dispatch thread and the dispatch thread is awoken by
4218            // the dispose call, there will be no race checking the peer's null
4219            // status.
4220    
4221            ComponentPeer tmp = peer;
4222            peer = null;
4223            peerFont = null;
4224            if (tmp != null)
4225              {
4226                tmp.hide();
4227                tmp.dispose();
4228              }
4229    
4230            // Notify hierarchy listeners.
4231            long flags = HierarchyEvent.DISPLAYABILITY_CHANGED;
4232            if (isHierarchyVisible())
4233              flags |= HierarchyEvent.SHOWING_CHANGED;
4234            fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, this, parent,
4235                               flags);
4236          }
4237      }
4238    
4239      /**
4240       * AWT 1.0 GOT_FOCUS event handler.  This method is meant to be
4241       * overridden by components providing their own GOT_FOCUS handler.
4242       * The default implementation simply returns false.
4243       *
4244       * @param evt the event to handle
4245       * @param what the Object focused, ignored
4246       * @return false
4247       * @deprecated use {@link #processFocusEvent(FocusEvent)} instead
4248       */
4249      public boolean gotFocus(Event evt, Object what)
4250      {
4251        return false;
4252      }
4253    
4254      /**
4255       * AWT 1.0 LOST_FOCUS event handler.  This method is meant to be
4256       * overridden by components providing their own LOST_FOCUS handler.
4257       * The default implementation simply returns false.
4258       *
4259       * @param evt the event to handle
4260       * @param what the Object focused, ignored
4261       * @return false
4262       * @deprecated use {@link #processFocusEvent(FocusEvent)} instead
4263       */
4264      public boolean lostFocus(Event evt, Object what)
4265      {
4266        return false;
4267      }
4268    
4269      /**
4270       * Tests whether or not this component is in the group that can be
4271       * traversed using the keyboard traversal mechanism (such as the TAB key).
4272       *
4273       * @return true if the component is traversed via the TAB key
4274       * @see #setFocusable(boolean)
4275       * @since 1.1
4276       * @deprecated use {@link #isFocusable()} instead
4277       */
4278      public boolean isFocusTraversable()
4279      {
4280        return enabled && visible && (peer == null || isLightweight() || peer.isFocusTraversable());
4281      }
4282    
4283      /**
4284       * Tests if this component can receive focus.
4285       *
4286       * @return true if this component can receive focus
4287       * @since 1.4
4288       */
4289      public boolean isFocusable()
4290      {
4291        return focusable;
4292      }
4293    
4294      /**
4295       * Specify whether this component can receive focus. This method also
4296       * sets the {@link #isFocusTraversableOverridden} field to 1, which
4297       * appears to be the undocumented way {@link
4298       * DefaultFocusTraversalPolicy#accept(Component)} determines whether to
4299       * respect the {@link #isFocusable()} method of the component.
4300       *
4301       * @param focusable the new focusable status
4302       * @since 1.4
4303       */
4304      public void setFocusable(boolean focusable)
4305      {
4306        firePropertyChange("focusable", this.focusable, focusable);
4307        this.focusable = focusable;
4308        this.isFocusTraversableOverridden = 1;
4309      }
4310    
4311      /**
4312       * Sets the focus traversal keys for one of the three focus
4313       * traversal directions supported by Components:
4314       * {@link KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS},
4315       * {@link KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS}, or
4316       * {@link KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS}. Normally, the
4317       * default values should match the operating system's native
4318       * choices. To disable a given traversal, use
4319       * <code>Collections.EMPTY_SET</code>. The event dispatcher will
4320       * consume PRESSED, RELEASED, and TYPED events for the specified
4321       * key, although focus can only transfer on PRESSED or RELEASED.
4322       *
4323       * <p>The defaults are:
4324       * <table>
4325       *   <th><td>Identifier</td><td>Meaning</td><td>Default</td></th>
4326       *   <tr><td>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</td>
4327       *     <td>Normal forward traversal</td>
4328       *     <td>TAB on KEY_PRESSED, Ctrl-TAB on KEY_PRESSED</td></tr>
4329       *   <tr><td>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</td>
4330       *     <td>Normal backward traversal</td>
4331       *     <td>Shift-TAB on KEY_PRESSED, Ctrl-Shift-TAB on KEY_PRESSED</td></tr>
4332       *   <tr><td>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</td>
4333       *     <td>Go up a traversal cycle</td><td>None</td></tr>
4334       * </table>
4335       *
4336       * If keystrokes is null, this component's focus traversal key set
4337       * is inherited from one of its ancestors.  If none of its ancestors
4338       * has its own set of focus traversal keys, the focus traversal keys
4339       * are set to the defaults retrieved from the current
4340       * KeyboardFocusManager.  If not null, the set must contain only
4341       * AWTKeyStrokes that are not already focus keys and are not
4342       * KEY_TYPED events.
4343       *
4344       * @param id one of FORWARD_TRAVERSAL_KEYS, BACKWARD_TRAVERSAL_KEYS, or
4345       *        UP_CYCLE_TRAVERSAL_KEYS
4346       * @param keystrokes a set of keys, or null
4347       * @throws IllegalArgumentException if id or keystrokes is invalid
4348       * @see #getFocusTraversalKeys(int)
4349       * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS
4350       * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS
4351       * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
4352       * @since 1.4
4353       */
4354      public void setFocusTraversalKeys(int id,
4355                                        Set<? extends AWTKeyStroke> keystrokes)
4356      {
4357        if (keystrokes == null)
4358          {
4359            Container parent = getParent ();
4360    
4361            while (parent != null)
4362              {
4363                if (parent.areFocusTraversalKeysSet (id))
4364                  {
4365                    keystrokes = parent.getFocusTraversalKeys (id);
4366                    break;
4367                  }
4368                parent = parent.getParent ();
4369              }
4370    
4371            if (keystrokes == null)
4372              keystrokes = KeyboardFocusManager.getCurrentKeyboardFocusManager ().
4373                getDefaultFocusTraversalKeys (id);
4374          }
4375    
4376        Set sa;
4377        Set sb;
4378        String name;
4379        switch (id)
4380          {
4381          case KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS:
4382            sa = getFocusTraversalKeys
4383              (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
4384            sb = getFocusTraversalKeys
4385              (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
4386            name = "forwardFocusTraversalKeys";
4387            break;
4388          case KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS:
4389            sa = getFocusTraversalKeys
4390              (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
4391            sb = getFocusTraversalKeys
4392              (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
4393            name = "backwardFocusTraversalKeys";
4394            break;
4395          case KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS:
4396            sa = getFocusTraversalKeys
4397              (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
4398            sb = getFocusTraversalKeys
4399              (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
4400            name = "upCycleFocusTraversalKeys";
4401            break;
4402          default:
4403            throw new IllegalArgumentException ();
4404          }
4405    
4406        int i = keystrokes.size ();
4407        Iterator iter = keystrokes.iterator ();
4408    
4409        while (--i >= 0)
4410          {
4411            Object o = iter.next ();
4412            if (!(o instanceof AWTKeyStroke)
4413                || sa.contains (o) || sb.contains (o)
4414                || ((AWTKeyStroke) o).keyCode == KeyEvent.VK_UNDEFINED)
4415              throw new IllegalArgumentException ();
4416          }
4417    
4418        if (focusTraversalKeys == null)
4419          focusTraversalKeys = new Set[3];
4420    
4421        keystrokes = Collections.unmodifiableSet (new HashSet (keystrokes));
4422        firePropertyChange (name, focusTraversalKeys[id], keystrokes);
4423    
4424        focusTraversalKeys[id] = keystrokes;
4425      }
4426    
4427      /**
4428       * Returns the set of keys for a given focus traversal action, as
4429       * defined in <code>setFocusTraversalKeys</code>.  If not set, this
4430       * is inherited from the parent component, which may have gotten it
4431       * from the KeyboardFocusManager.
4432       *
4433       * @param id one of FORWARD_TRAVERSAL_KEYS, BACKWARD_TRAVERSAL_KEYS,
4434       * or UP_CYCLE_TRAVERSAL_KEYS
4435       *
4436       * @return set of traversal keys
4437       *
4438       * @throws IllegalArgumentException if id is invalid
4439       * 
4440       * @see #setFocusTraversalKeys (int, Set)
4441       * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS
4442       * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS
4443       * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
4444       * 
4445       * @since 1.4
4446       */
4447      public Set<AWTKeyStroke> getFocusTraversalKeys (int id)
4448      {
4449        if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
4450            id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
4451            id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS)
4452          throw new IllegalArgumentException();
4453    
4454        Set<AWTKeyStroke> s = null;
4455    
4456        if (focusTraversalKeys != null)
4457          s = focusTraversalKeys[id];
4458    
4459        if (s == null && parent != null)
4460          s = parent.getFocusTraversalKeys (id);
4461    
4462        return s == null ? (KeyboardFocusManager.getCurrentKeyboardFocusManager()
4463                            .getDefaultFocusTraversalKeys(id)) : s;
4464      }
4465    
4466      /**
4467       * Tests whether the focus traversal keys for a given action are explicitly
4468       * set or inherited.
4469       *
4470       * @param id one of FORWARD_TRAVERSAL_KEYS, BACKWARD_TRAVERSAL_KEYS,
4471       * or UP_CYCLE_TRAVERSAL_KEYS
4472       * @return true if that set is explicitly specified
4473       * @throws IllegalArgumentException if id is invalid
4474       * @see #getFocusTraversalKeys (int)
4475       * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS
4476       * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS
4477       * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
4478       * @since 1.4
4479       */
4480      public boolean areFocusTraversalKeysSet (int id)
4481      {
4482        if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
4483            id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
4484            id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS)
4485          throw new IllegalArgumentException ();
4486    
4487        return focusTraversalKeys != null && focusTraversalKeys[id] != null;
4488      }
4489    
4490      /**
4491       * Enable or disable focus traversal keys on this Component.  If
4492       * they are, then the keyboard focus manager consumes and acts on
4493       * key press and release events that trigger focus traversal, and
4494       * discards the corresponding key typed events.  If focus traversal
4495       * keys are disabled, then all key events that would otherwise
4496       * trigger focus traversal are sent to this Component.
4497       *
4498       * @param focusTraversalKeysEnabled the new value of the flag
4499       * @see #getFocusTraversalKeysEnabled ()
4500       * @see #setFocusTraversalKeys (int, Set)
4501       * @see #getFocusTraversalKeys (int)
4502       * @since 1.4
4503       */
4504      public void setFocusTraversalKeysEnabled (boolean focusTraversalKeysEnabled)
4505      {
4506        firePropertyChange ("focusTraversalKeysEnabled",
4507                            this.focusTraversalKeysEnabled,
4508                            focusTraversalKeysEnabled);
4509        this.focusTraversalKeysEnabled = focusTraversalKeysEnabled;
4510      }
4511    
4512      /**
4513       * Check whether or not focus traversal keys are enabled on this
4514       * Component.  If they are, then the keyboard focus manager consumes
4515       * and acts on key press and release events that trigger focus
4516       * traversal, and discards the corresponding key typed events.  If
4517       * focus traversal keys are disabled, then all key events that would
4518       * otherwise trigger focus traversal are sent to this Component.
4519       *
4520       * @return true if focus traversal keys are enabled
4521       * @see #setFocusTraversalKeysEnabled (boolean)
4522       * @see #setFocusTraversalKeys (int, Set)
4523       * @see #getFocusTraversalKeys (int)
4524       * @since 1.4
4525       */
4526      public boolean getFocusTraversalKeysEnabled ()
4527      {
4528        return focusTraversalKeysEnabled;
4529      }
4530    
4531      /**
4532       * Request that this Component be given the keyboard input focus and
4533       * that its top-level ancestor become the focused Window.
4534       *
4535       * For the request to be granted, the Component must be focusable,
4536       * displayable and showing and the top-level Window to which it
4537       * belongs must be focusable.  If the request is initially denied on
4538       * the basis that the top-level Window is not focusable, the request
4539       * will be remembered and granted when the Window does become
4540       * focused.
4541       *
4542       * Never assume that this Component is the focus owner until it
4543       * receives a FOCUS_GAINED event.
4544       *
4545       * The behaviour of this method is platform-dependent.
4546       * {@link #requestFocusInWindow()} should be used instead.
4547       *
4548       * @see #requestFocusInWindow ()
4549       * @see FocusEvent
4550       * @see #addFocusListener (FocusListener)
4551       * @see #isFocusable ()
4552       * @see #isDisplayable ()
4553       * @see KeyboardFocusManager#clearGlobalFocusOwner ()
4554       */
4555      public void requestFocus ()
4556      {
4557        requestFocusImpl(false, true);
4558      }
4559    
4560      /**
4561       * Request that this Component be given the keyboard input focus and
4562       * that its top-level ancestor become the focused Window.
4563       *
4564       * For the request to be granted, the Component must be focusable,
4565       * displayable and showing and the top-level Window to which it
4566       * belongs must be focusable.  If the request is initially denied on
4567       * the basis that the top-level Window is not focusable, the request
4568       * will be remembered and granted when the Window does become
4569       * focused.
4570       *
4571       * Never assume that this Component is the focus owner until it
4572       * receives a FOCUS_GAINED event.
4573       *
4574       * The behaviour of this method is platform-dependent.
4575       * {@link #requestFocusInWindow()} should be used instead.
4576       *
4577       * If the return value is false, the request is guaranteed to fail.
4578       * If the return value is true, the request will succeed unless it
4579       * is vetoed or something in the native windowing system intervenes,
4580       * preventing this Component's top-level ancestor from becoming
4581       * focused.  This method is meant to be called by derived
4582       * lightweight Components that want to avoid unnecessary repainting
4583       * when they know a given focus transfer need only be temporary.
4584       *
4585       * @param temporary true if the focus request is temporary
4586       * @return true if the request has a chance of success
4587       * @see #requestFocusInWindow ()
4588       * @see FocusEvent
4589       * @see #addFocusListener (FocusListener)
4590       * @see #isFocusable ()
4591       * @see #isDisplayable ()
4592       * @see KeyboardFocusManager#clearGlobalFocusOwner ()
4593       * @since 1.4
4594       */
4595      protected boolean requestFocus (boolean temporary)
4596      {
4597        return requestFocusImpl(temporary, true);
4598      }
4599    
4600      /**
4601       * Request that this component be given the keyboard input focus, if
4602       * its top-level ancestor is the currently focused Window.  A
4603       * <code>FOCUS_GAINED</code> event will be fired if and only if this
4604       * request is successful. To be successful, the component must be
4605       * displayable, showing, and focusable, and its ancestor top-level
4606       * Window must be focused.
4607       *
4608       * If the return value is false, the request is guaranteed to fail.
4609       * If the return value is true, the request will succeed unless it
4610       * is vetoed or something in the native windowing system intervenes,
4611       * preventing this Component's top-level ancestor from becoming
4612       * focused.
4613       *
4614       * @return true if the request has a chance of success
4615       * @see #requestFocus ()
4616       * @see FocusEvent
4617       * @see #addFocusListener (FocusListener)
4618       * @see #isFocusable ()
4619       * @see #isDisplayable ()
4620       * @see KeyboardFocusManager#clearGlobalFocusOwner ()
4621       * @since 1.4
4622       */
4623      public boolean requestFocusInWindow ()
4624      {
4625        return requestFocusImpl(false, false);
4626      }
4627    
4628      /**
4629       * Request that this component be given the keyboard input focus, if
4630       * its top-level ancestor is the currently focused Window.  A
4631       * <code>FOCUS_GAINED</code> event will be fired if and only if this
4632       * request is successful. To be successful, the component must be
4633       * displayable, showing, and focusable, and its ancestor top-level
4634       * Window must be focused.
4635       *
4636       * If the return value is false, the request is guaranteed to fail.
4637       * If the return value is true, the request will succeed unless it
4638       * is vetoed or something in the native windowing system intervenes,
4639       * preventing this Component's top-level ancestor from becoming
4640       * focused.  This method is meant to be called by derived
4641       * lightweight Components that want to avoid unnecessary repainting
4642       * when they know a given focus transfer need only be temporary.
4643       *
4644       * @param temporary true if the focus request is temporary
4645       * @return true if the request has a chance of success
4646       * @see #requestFocus ()
4647       * @see FocusEvent
4648       * @see #addFocusListener (FocusListener)
4649       * @see #isFocusable ()
4650       * @see #isDisplayable ()
4651       * @see KeyboardFocusManager#clearGlobalFocusOwner ()
4652       * @since 1.4
4653       */
4654      protected boolean requestFocusInWindow (boolean temporary)
4655      {
4656        return requestFocusImpl(temporary, false);
4657      }
4658    
4659      /**
4660       * Helper method for all 4 requestFocus variants.
4661       *
4662       * @param temporary indicates if the focus change is temporary
4663       * @param focusWindow indicates if the window focus may be changed
4664       *
4665       * @return <code>false</code> if the request has been definitely denied,
4666       *         <code>true</code> otherwise
4667       */
4668      private boolean requestFocusImpl(boolean temporary, boolean focusWindow)
4669      {
4670        boolean retval = false;
4671     
4672        // Don't try to focus non-focusable and non-visible components.
4673        if (isFocusable() && isVisible())
4674          {
4675            ComponentPeer myPeer = peer;
4676            if (peer != null)
4677              {
4678                // Find Window ancestor and find out if we're showing while
4679                // doing this.
4680                boolean showing = true;
4681                Component window = this;
4682                while (! (window instanceof Window))
4683                  {
4684                    if (! window.isVisible())
4685                      showing = false;
4686                    window = window.parent;
4687                  }
4688                // Don't allow focus when there is no window or the window
4689                // is not focusable.
4690                if (window != null && ((Window) window).isFocusableWindow()
4691                    && showing)
4692                  {
4693                    // Search for nearest heavy ancestor (including this
4694                    // component).
4695                    Component heavyweightParent = this;
4696                    while (heavyweightParent.peer instanceof LightweightPeer)
4697                      heavyweightParent = heavyweightParent.parent;
4698    
4699                    // Don't allow focus on lightweight components without
4700                    // visible heavyweight ancestor
4701                    if (heavyweightParent != null && heavyweightParent.isVisible())
4702                      {
4703                        // Don't allow focus when heavyweightParent has no peer.
4704                        myPeer = heavyweightParent.peer;
4705                        if (myPeer != null)
4706                          {
4707                            // Register lightweight focus request.
4708                            if (heavyweightParent != this)
4709                              {
4710                                KeyboardFocusManager
4711                                .addLightweightFocusRequest(heavyweightParent,
4712                                                            this);
4713                              }
4714    
4715                            // Try to focus the component.
4716                            long time = EventQueue.getMostRecentEventTime();
4717                            boolean success = myPeer.requestFocus(this, temporary,
4718                                                                  focusWindow,
4719                                                                  time);
4720                            if (! success)
4721                              {
4722                                // Dequeue key events if focus request failed.
4723                                KeyboardFocusManager kfm =
4724                                  KeyboardFocusManager.getCurrentKeyboardFocusManager();
4725                                kfm.dequeueKeyEvents(time, this);
4726                              }
4727                            retval = success;
4728                          }
4729                      }
4730                  }
4731              }
4732          }
4733        return retval;
4734      }
4735    
4736      /**
4737       * Transfers focus to the next component in the focus traversal
4738       * order, as though this were the current focus owner.
4739       *
4740       * @see #requestFocus()
4741       * @since 1.1
4742       */
4743      public void transferFocus ()
4744      {
4745        nextFocus ();
4746      }
4747    
4748      /**
4749       * Returns the root container that owns the focus cycle where this
4750       * component resides. A focus cycle root is in two cycles, one as
4751       * the ancestor, and one as the focusable element; this call always
4752       * returns the ancestor.
4753       *
4754       * @return the ancestor container that owns the focus cycle
4755       * @since 1.4
4756       */
4757      public Container getFocusCycleRootAncestor ()
4758      {
4759        Container parent = getParent ();
4760    
4761        while (parent != null && !parent.isFocusCycleRoot())
4762          parent = parent.getParent ();
4763    
4764        return parent;
4765      }
4766    
4767      /**
4768       * Tests if the container is the ancestor of the focus cycle that
4769       * this component belongs to.
4770       *
4771       * @param c the container to test
4772       * @return true if c is the focus cycle root
4773       * @since 1.4
4774       */
4775      public boolean isFocusCycleRoot (Container c)
4776      {
4777        return c == getFocusCycleRootAncestor ();
4778      }
4779    
4780      /**
4781       * AWT 1.0 focus event processor.  Transfers focus to the next
4782       * component in the focus traversal order, as though this were the
4783       * current focus owner.
4784       *
4785       * @deprecated use {@link #transferFocus ()} instead
4786       */
4787      public void nextFocus ()
4788      {
4789        // Find the nearest valid (== showing && focusable && enabled) focus
4790        // cycle root ancestor and the focused component in it.
4791        Container focusRoot = getFocusCycleRootAncestor();
4792        Component focusComp = this;
4793        while (focusRoot != null
4794               && ! (focusRoot.isShowing() && focusRoot.isFocusable()
4795                     && focusRoot.isEnabled()))
4796          {
4797            focusComp = focusRoot;
4798            focusRoot = focusComp.getFocusCycleRootAncestor();
4799          }
4800    
4801        if (focusRoot != null)
4802          {
4803            // First try to get the componentBefore from the policy.
4804            FocusTraversalPolicy policy = focusRoot.getFocusTraversalPolicy();
4805            Component nextFocus = policy.getComponentAfter(focusRoot, focusComp);
4806    
4807            // If this fails, then ask for the defaultComponent.
4808            if (nextFocus == null)
4809              nextFocus = policy.getDefaultComponent(focusRoot);
4810    
4811            // Request focus on this component, if not null.
4812            if (nextFocus != null)
4813              nextFocus.requestFocus();
4814          }
4815      }
4816    
4817      /**
4818       * Transfers focus to the previous component in the focus traversal
4819       * order, as though this were the current focus owner.
4820       *
4821       * @see #requestFocus ()
4822       * @since 1.4
4823       */
4824      public void transferFocusBackward ()
4825      {
4826        // Find the nearest valid (== showing && focusable && enabled) focus
4827        // cycle root ancestor and the focused component in it.
4828        Container focusRoot = getFocusCycleRootAncestor();
4829        Component focusComp = this;
4830        while (focusRoot != null
4831               && ! (focusRoot.isShowing() && focusRoot.isFocusable()
4832                     && focusRoot.isEnabled()))
4833          {
4834            focusComp = focusRoot;
4835            focusRoot = focusComp.getFocusCycleRootAncestor();
4836          }
4837    
4838        if (focusRoot != null)
4839          {
4840            // First try to get the componentBefore from the policy.
4841            FocusTraversalPolicy policy = focusRoot.getFocusTraversalPolicy();
4842            Component nextFocus = policy.getComponentBefore(focusRoot, focusComp);
4843    
4844            // If this fails, then ask for the defaultComponent.
4845            if (nextFocus == null)
4846              nextFocus = policy.getDefaultComponent(focusRoot);
4847    
4848            // Request focus on this component, if not null.
4849            if (nextFocus != null)
4850              nextFocus.requestFocus();
4851          }
4852      }
4853    
4854      /**
4855       * Transfers focus to the focus cycle root of this component.
4856       * However, if this is a Window, the default focus owner in the
4857       * window in the current focus cycle is focused instead.
4858       *
4859       * @see #requestFocus()
4860       * @see #isFocusCycleRoot(Container)
4861       * @since 1.4
4862       */
4863      public void transferFocusUpCycle ()
4864      {
4865        // Find the nearest focus cycle root ancestor that is itself
4866        // focusable, showing and enabled.
4867        Container focusCycleRoot = getFocusCycleRootAncestor();
4868        while (focusCycleRoot != null &&
4869               ! (focusCycleRoot.isShowing() && focusCycleRoot.isFocusable()
4870                  && focusCycleRoot.isEnabled()))
4871          {
4872            focusCycleRoot = focusCycleRoot.getFocusCycleRootAncestor();
4873          }
4874    
4875        KeyboardFocusManager fm =
4876          KeyboardFocusManager.getCurrentKeyboardFocusManager();
4877    
4878        if (focusCycleRoot != null)
4879          {
4880            // If we found a focus cycle root, then we make this the new
4881            // focused component, and make it's focus cycle root the new
4882            // global focus cycle root. If the found root has no focus cycle
4883            // root ancestor itself, then the component will be both the focused
4884            // component and the new global focus cycle root.
4885            Container focusCycleAncestor =
4886              focusCycleRoot.getFocusCycleRootAncestor();
4887            Container globalFocusCycleRoot;
4888            if (focusCycleAncestor == null)
4889              globalFocusCycleRoot = focusCycleRoot;
4890            else
4891              globalFocusCycleRoot = focusCycleAncestor;
4892    
4893            fm.setGlobalCurrentFocusCycleRoot(globalFocusCycleRoot);
4894            focusCycleRoot.requestFocus();
4895          }
4896        else
4897          {
4898            // If this component has no applicable focus cycle root, we try
4899            // find the nearest window and set this as the new global focus cycle
4900            // root and the default focus component of this window the new focused
4901            // component.
4902            Container cont;
4903            if (this instanceof Container)
4904              cont = (Container) this;
4905            else
4906              cont = getParent();
4907    
4908            while (cont != null && !(cont instanceof Window))
4909              cont = cont.getParent();
4910    
4911            if (cont != null)
4912              {
4913                FocusTraversalPolicy policy = cont.getFocusTraversalPolicy();
4914                Component focusComp = policy.getDefaultComponent(cont);
4915                if (focusComp != null)
4916                  {
4917                    fm.setGlobalCurrentFocusCycleRoot(cont);
4918                    focusComp.requestFocus();
4919                  }
4920              }
4921          }
4922      }
4923    
4924      /**
4925       * Tests if this component is the focus owner. Use {@link
4926       * #isFocusOwner ()} instead.
4927       *
4928       * @return true if this component owns focus
4929       * @since 1.2
4930       */
4931      public boolean hasFocus ()
4932      {
4933        KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
4934    
4935        Component focusOwner = manager.getFocusOwner ();
4936    
4937        return this == focusOwner;
4938      }
4939    
4940      /**
4941       * Tests if this component is the focus owner.
4942       *
4943       * @return true if this component owns focus
4944       * @since 1.4
4945       */
4946      public boolean isFocusOwner()
4947      {
4948        return hasFocus ();
4949      }
4950    
4951      /**
4952       * Adds the specified popup menu to this component.
4953       *
4954       * @param popup the popup menu to be added
4955       * 
4956       * @see #remove(MenuComponent)
4957       * 
4958       * @since 1.1
4959       */
4960      public synchronized void add(PopupMenu popup)
4961      {
4962        if (popups == null)
4963          popups = new Vector();
4964        popups.add(popup);
4965    
4966        if (popup.parent != null)
4967          popup.parent.remove(popup);
4968        popup.parent = this;
4969        if (peer != null)
4970          popup.addNotify();
4971      }
4972    
4973      /**
4974       * Removes the specified popup menu from this component.
4975       *
4976       * @param popup the popup menu to remove
4977       * @see #add(PopupMenu)
4978       * @since 1.1
4979       */
4980      public synchronized void remove(MenuComponent popup)
4981      {
4982        if (popups != null)
4983          popups.remove(popup);
4984      }
4985    
4986      /**
4987       * Returns a debugging string representing this component. The string may
4988       * be empty but not null.
4989       *
4990       * @return a string representing this component
4991       */
4992      protected String paramString()
4993      {
4994        StringBuffer param = new StringBuffer();
4995        String name = getName();
4996        if (name != null)
4997          param.append(name).append(",");
4998        param.append(x).append(",").append(y).append(",").append(width)
4999          .append("x").append(height);
5000        if (! isValid())
5001          param.append(",invalid");
5002        if (! isVisible())
5003          param.append(",invisible");
5004        if (! isEnabled())
5005          param.append(",disabled");
5006        if (! isOpaque())
5007          param.append(",translucent");
5008        if (isDoubleBuffered())
5009          param.append(",doublebuffered");
5010        if (parent == null)
5011          param.append(",parent=null");
5012        else
5013          param.append(",parent=").append(parent.getName());
5014        return param.toString();
5015      }
5016    
5017      /**
5018       * Returns a string representation of this component. This is implemented
5019       * as <code>getClass().getName() + '[' + paramString() + ']'</code>.
5020       *
5021       * @return a string representation of this component
5022       */
5023      public String toString()
5024      {
5025        return getClass().getName() + '[' + paramString() + ']';
5026      }
5027    
5028      /**
5029       * Prints a listing of this component to <code>System.out</code>.
5030       *
5031       * @see #list(PrintStream)
5032       */
5033      public void list()
5034      {
5035        list(System.out, 0);
5036      }
5037    
5038      /**
5039       * Prints a listing of this component to the specified print stream.
5040       *
5041       * @param out the <code>PrintStream</code> to print to
5042       */
5043      public void list(PrintStream out)
5044      {
5045        list(out, 0);
5046      }
5047    
5048      /**
5049       * Prints a listing of this component to the specified print stream,
5050       * starting at the specified indentation point.
5051       *
5052       * @param out the <code>PrintStream</code> to print to
5053       * @param indent the indentation point
5054       */
5055      public void list(PrintStream out, int indent)
5056      {
5057        for (int i = 0; i < indent; ++i)
5058          out.print(' ');
5059        out.println(toString());
5060      }
5061    
5062      /**
5063       * Prints a listing of this component to the specified print writer.
5064       *
5065       * @param out the <code>PrintWrinter</code> to print to
5066       * @since 1.1
5067       */
5068      public void list(PrintWriter out)
5069      {
5070        list(out, 0);
5071      }
5072    
5073      /**
5074       * Prints a listing of this component to the specified print writer,
5075       * starting at the specified indentation point.
5076       *
5077       * @param out the <code>PrintWriter</code> to print to
5078       * @param indent the indentation point
5079       * @since 1.1
5080       */
5081      public void list(PrintWriter out, int indent)
5082      {
5083        for (int i = 0; i < indent; ++i)
5084          out.print(' ');
5085        out.println(toString());
5086      }
5087    
5088      /**
5089       * Adds the specified property listener to this component. This is harmless
5090       * if the listener is null, but if the listener has already been registered,
5091       * it will now be registered twice. The property listener ignores inherited
5092       * properties. Recognized properties include:<br>
5093       * <ul>
5094       * <li>the font (<code>"font"</code>)</li>
5095       * <li>the background color (<code>"background"</code>)</li>
5096       * <li>the foreground color (<code>"foreground"</code>)</li>
5097       * <li>the focusability (<code>"focusable"</code>)</li>
5098       * <li>the focus key traversal enabled state
5099       *     (<code>"focusTraversalKeysEnabled"</code>)</li>
5100       * <li>the set of forward traversal keys
5101       *     (<code>"forwardFocusTraversalKeys"</code>)</li>
5102       * <li>the set of backward traversal keys
5103       *     (<code>"backwardFocusTraversalKeys"</code>)</li>
5104       * <li>the set of up-cycle traversal keys
5105       *     (<code>"upCycleFocusTraversalKeys"</code>)</li>
5106       * </ul>
5107       *
5108       * @param listener the new listener to add
5109       * @see #removePropertyChangeListener(PropertyChangeListener)
5110       * @see #getPropertyChangeListeners()
5111       * @see #addPropertyChangeListener(String, PropertyChangeListener)
5112       * @since 1.1
5113       */
5114      public void addPropertyChangeListener(PropertyChangeListener listener)
5115      {
5116        if (changeSupport == null)
5117          changeSupport = new PropertyChangeSupport(this);
5118        changeSupport.addPropertyChangeListener(listener);
5119      }
5120    
5121      /**
5122       * Removes the specified property listener from the component. This is
5123       * harmless if the listener was not previously registered.
5124       *
5125       * @param listener the listener to remove
5126       * @see #addPropertyChangeListener(PropertyChangeListener)
5127       * @see #getPropertyChangeListeners()
5128       * @see #removePropertyChangeListener(String, PropertyChangeListener)
5129       * @since 1.1
5130       */
5131      public void removePropertyChangeListener(PropertyChangeListener listener)
5132      {
5133        if (changeSupport != null)
5134          changeSupport.removePropertyChangeListener(listener);
5135      }
5136    
5137      /**
5138       * Returns an array of all specified listeners registered on this component.
5139       *
5140       * @return an array of listeners
5141       * @see #addPropertyChangeListener(PropertyChangeListener)
5142       * @see #removePropertyChangeListener(PropertyChangeListener)
5143       * @see #getPropertyChangeListeners(String)
5144       * @since 1.4
5145       */
5146      public PropertyChangeListener[] getPropertyChangeListeners()
5147      {
5148        return changeSupport == null ? new PropertyChangeListener[0]
5149          : changeSupport.getPropertyChangeListeners();
5150      }
5151    
5152      /**
5153       * Adds the specified property listener to this component. This is harmless
5154       * if the listener is null, but if the listener has already been registered,
5155       * it will now be registered twice. The property listener ignores inherited
5156       * properties. The listener is keyed to a single property. Recognized
5157       * properties include:<br>
5158       * <ul>
5159       * <li>the font (<code>"font"</code>)</li>
5160       * <li>the background color (<code>"background"</code>)</li>
5161       * <li>the foreground color (<code>"foreground"</code>)</li>
5162       * <li>the focusability (<code>"focusable"</code>)</li>
5163       * <li>the focus key traversal enabled state
5164       *     (<code>"focusTraversalKeysEnabled"</code>)</li>
5165       * <li>the set of forward traversal keys
5166       *     (<code>"forwardFocusTraversalKeys"</code>)</li>
5167    p   * <li>the set of backward traversal keys
5168       *     (<code>"backwardFocusTraversalKeys"</code>)</li>
5169       * <li>the set of up-cycle traversal keys
5170       *     (<code>"upCycleFocusTraversalKeys"</code>)</li>
5171       * </ul>
5172       *
5173       * @param propertyName the property name to filter on
5174       * @param listener the new listener to add
5175       * @see #removePropertyChangeListener(String, PropertyChangeListener)
5176       * @see #getPropertyChangeListeners(String)
5177       * @see #addPropertyChangeListener(PropertyChangeListener)
5178       * @since 1.1
5179       */
5180      public void addPropertyChangeListener(String propertyName,
5181                                            PropertyChangeListener listener)
5182      {
5183        if (changeSupport == null)
5184          changeSupport = new PropertyChangeSupport(this);
5185        changeSupport.addPropertyChangeListener(propertyName, listener);
5186      }
5187    
5188      /**
5189       * Removes the specified property listener on a particular property from
5190       * the component. This is harmless if the listener was not previously
5191       * registered.
5192       *
5193       * @param propertyName the property name to filter on
5194       * @param listener the listener to remove
5195       * @see #addPropertyChangeListener(String, PropertyChangeListener)
5196       * @see #getPropertyChangeListeners(String)
5197       * @see #removePropertyChangeListener(PropertyChangeListener)
5198       * @since 1.1
5199       */
5200      public void removePropertyChangeListener(String propertyName,
5201                                               PropertyChangeListener listener)
5202      {
5203        if (changeSupport != null)
5204          changeSupport.removePropertyChangeListener(propertyName, listener);
5205      }
5206    
5207      /**
5208       * Returns an array of all specified listeners on the named property that
5209       * are registered on this component.
5210       *
5211       * @return an array of listeners
5212       * @see #addPropertyChangeListener(String, PropertyChangeListener)
5213       * @see #removePropertyChangeListener(String, PropertyChangeListener)
5214       * @see #getPropertyChangeListeners()
5215       * @since 1.4
5216       */
5217      public PropertyChangeListener[] getPropertyChangeListeners(String property)
5218      {
5219        return changeSupport == null ? new PropertyChangeListener[0]
5220          : changeSupport.getPropertyChangeListeners(property);
5221      }
5222    
5223      /**
5224       * Report a change in a bound property to any registered property listeners.
5225       *
5226       * @param propertyName the property that changed
5227       * @param oldValue the old property value
5228       * @param newValue the new property value
5229       */
5230      protected void firePropertyChange(String propertyName, Object oldValue,
5231                                        Object newValue)
5232      {
5233        if (changeSupport != null)
5234          changeSupport.firePropertyChange(propertyName, oldValue, newValue);  
5235      }
5236    
5237      /**
5238       * Report a change in a bound property to any registered property listeners.
5239       *
5240       * @param propertyName the property that changed
5241       * @param oldValue the old property value
5242       * @param newValue the new property value
5243       */
5244      protected void firePropertyChange(String propertyName, boolean oldValue,
5245                                        boolean newValue)
5246      {
5247        if (changeSupport != null)
5248          changeSupport.firePropertyChange(propertyName, oldValue, newValue);
5249      }
5250    
5251      /**
5252       * Report a change in a bound property to any registered property listeners.
5253       *
5254       * @param propertyName the property that changed
5255       * @param oldValue the old property value
5256       * @param newValue the new property value
5257       */
5258      protected void firePropertyChange(String propertyName, int oldValue,
5259                                        int newValue)
5260      {
5261        if (changeSupport != null)
5262          changeSupport.firePropertyChange(propertyName, oldValue, newValue);
5263      }
5264    
5265      /**
5266       * Report a change in a bound property to any registered property listeners.
5267       *
5268       * @param propertyName the property that changed
5269       * @param oldValue the old property value
5270       * @param newValue the new property value
5271       *
5272       * @since 1.5
5273       */
5274      public void firePropertyChange(String propertyName, byte oldValue,
5275                                        byte newValue)
5276      {
5277        if (changeSupport != null)
5278          changeSupport.firePropertyChange(propertyName, new Byte(oldValue),
5279                                           new Byte(newValue));
5280      }
5281    
5282      /**
5283       * Report a change in a bound property to any registered property listeners.
5284       *
5285       * @param propertyName the property that changed
5286       * @param oldValue the old property value
5287       * @param newValue the new property value
5288       *
5289       * @since 1.5
5290       */
5291      public void firePropertyChange(String propertyName, char oldValue,
5292                                        char newValue)
5293      {
5294        if (changeSupport != null)
5295          changeSupport.firePropertyChange(propertyName, new Character(oldValue),
5296                                           new Character(newValue));
5297      }
5298    
5299      /**
5300       * Report a change in a bound property to any registered property listeners.
5301       *
5302       * @param propertyName the property that changed
5303       * @param oldValue the old property value
5304       * @param newValue the new property value
5305       *
5306       * @since 1.5
5307       */
5308      public void firePropertyChange(String propertyName, short oldValue,
5309                                        short newValue)
5310      {
5311        if (changeSupport != null)
5312          changeSupport.firePropertyChange(propertyName, new Short(oldValue),
5313                                           new Short(newValue));
5314      }
5315    
5316      /**
5317       * Report a change in a bound property to any registered property listeners.
5318       *
5319       * @param propertyName the property that changed
5320       * @param oldValue the old property value
5321       * @param newValue the new property value
5322       *
5323       * @since 1.5
5324       */
5325      public void firePropertyChange(String propertyName, long oldValue,
5326                                        long newValue)
5327      {
5328        if (changeSupport != null)
5329          changeSupport.firePropertyChange(propertyName, new Long(oldValue),
5330                                           new Long(newValue));
5331      }
5332    
5333      /**
5334       * Report a change in a bound property to any registered property listeners.
5335       *
5336       * @param propertyName the property that changed
5337       * @param oldValue the old property value
5338       * @param newValue the new property value
5339       *
5340       * @since 1.5
5341       */
5342      public void firePropertyChange(String propertyName, float oldValue,
5343                                        float newValue)
5344      {
5345        if (changeSupport != null)
5346          changeSupport.firePropertyChange(propertyName, new Float(oldValue),
5347                                           new Float(newValue));
5348      }
5349    
5350    
5351      /**
5352       * Report a change in a bound property to any registered property listeners.
5353       *
5354       * @param propertyName the property that changed
5355       * @param oldValue the old property value
5356       * @param newValue the new property value
5357       *
5358       * @since 1.5
5359       */
5360      public void firePropertyChange(String propertyName, double oldValue,
5361                                     double newValue)
5362      {
5363        if (changeSupport != null)
5364          changeSupport.firePropertyChange(propertyName, new Double(oldValue),
5365                                           new Double(newValue));
5366      }
5367    
5368      /**
5369       * Sets the text layout orientation of this component. New components default
5370       * to UNKNOWN (which behaves like LEFT_TO_RIGHT). This method affects only
5371       * the current component, while
5372       * {@link #applyComponentOrientation(ComponentOrientation)} affects the
5373       * entire hierarchy.
5374       *
5375       * @param o the new orientation (<code>null</code> is accepted)
5376       * @see #getComponentOrientation()
5377       */
5378      public void setComponentOrientation(ComponentOrientation o)
5379      {
5380     
5381        ComponentOrientation oldOrientation = componentOrientation;
5382        componentOrientation = o;
5383        firePropertyChange("componentOrientation", oldOrientation, o);
5384      }
5385    
5386      /**
5387       * Determines the text layout orientation used by this component.
5388       *
5389       * @return the component orientation (this can be <code>null</code>)
5390       * @see #setComponentOrientation(ComponentOrientation)
5391       */
5392      public ComponentOrientation getComponentOrientation()
5393      {
5394        return componentOrientation;
5395      }
5396    
5397      /**
5398       * Sets the text layout orientation of this component. New components default
5399       * to UNKNOWN (which behaves like LEFT_TO_RIGHT). This method affects the
5400       * entire hierarchy, while
5401       * {@link #setComponentOrientation(ComponentOrientation)} affects only the
5402       * current component.
5403       *
5404       * @param o the new orientation
5405       * @throws NullPointerException if o is null
5406       * @see #getComponentOrientation()
5407       * @since 1.4
5408       */
5409      public void applyComponentOrientation(ComponentOrientation o)
5410      {
5411        setComponentOrientation(o);
5412      }
5413    
5414      /**
5415       * Returns the accessibility framework context of this class. Component is
5416       * not accessible, so the default implementation returns null. Subclasses
5417       * must override this behavior, and return an appropriate subclass of
5418       * {@link AccessibleAWTComponent}.
5419       *
5420       * @return the accessibility context
5421       */
5422      public AccessibleContext getAccessibleContext()
5423      {
5424        return null;
5425      }
5426    
5427    
5428      // Helper methods; some are package visible for use by subclasses.
5429    
5430      /**
5431       * Subclasses should override this to return unique component names like
5432       * "menuitem0".
5433       *
5434       * @return the generated name for this component
5435       */
5436      String generateName()
5437      {
5438        // Component is abstract.
5439        return null;
5440      }
5441    
5442      /**
5443       * Sets the peer for this component.
5444       *
5445       * @param peer the new peer
5446       */
5447      final void setPeer(ComponentPeer peer)
5448      {
5449        this.peer = peer;
5450      }
5451    
5452      /**
5453       * Translate an AWT 1.1 event ({@link AWTEvent}) into an AWT 1.0
5454       * event ({@link Event}).
5455       *
5456       * @param e an AWT 1.1 event to translate
5457       *
5458       * @return an AWT 1.0 event representing e
5459       */
5460      static Event translateEvent (AWTEvent e)
5461      {
5462        Object target = e.getSource ();
5463        Event translated = null;
5464        
5465        if (e instanceof WindowEvent)
5466          {
5467            WindowEvent we = (WindowEvent) e;
5468            int id = we.id;
5469            int newId = 0;
5470            
5471            switch (id)
5472              {
5473              case WindowEvent.WINDOW_DEICONIFIED:
5474                newId = Event.WINDOW_DEICONIFY;
5475                break;
5476              case WindowEvent.WINDOW_CLOSED:
5477              case WindowEvent.WINDOW_CLOSING:
5478                newId = Event.WINDOW_DESTROY;
5479                break;
5480              case WindowEvent.WINDOW_ICONIFIED:
5481                newId = Event.WINDOW_ICONIFY;
5482                break;
5483              case WindowEvent.WINDOW_GAINED_FOCUS:
5484                newId = Event.GOT_FOCUS;
5485                break;
5486              case WindowEvent.WINDOW_LOST_FOCUS:
5487                newId = Event.LOST_FOCUS;
5488                break;
5489              default:
5490                return null;
5491              }
5492    
5493            translated = new Event(target, 0, newId, 0, 0, 0, 0);
5494          }
5495        else if (e instanceof InputEvent)
5496          {
5497            InputEvent ie = (InputEvent) e;
5498            long when = ie.getWhen ();
5499    
5500            int oldID = 0;
5501            int id = e.getID ();
5502    
5503            int oldMods = 0;
5504            int mods = ie.getModifiersEx ();
5505    
5506            if ((mods & InputEvent.BUTTON2_DOWN_MASK) != 0)
5507              oldMods |= Event.META_MASK;
5508            else if ((mods & InputEvent.BUTTON3_DOWN_MASK) != 0)
5509              oldMods |= Event.ALT_MASK;
5510    
5511            if ((mods & InputEvent.SHIFT_DOWN_MASK) != 0)
5512              oldMods |= Event.SHIFT_MASK;
5513    
5514            if ((mods & InputEvent.CTRL_DOWN_MASK) != 0)
5515              oldMods |= Event.CTRL_MASK;
5516    
5517            if ((mods & InputEvent.META_DOWN_MASK) != 0)
5518              oldMods |= Event.META_MASK;
5519    
5520            if ((mods & InputEvent.ALT_DOWN_MASK) != 0)
5521              oldMods |= Event.ALT_MASK;
5522    
5523            if (e instanceof MouseEvent && !ignoreOldMouseEvents())
5524              {
5525                if (id == MouseEvent.MOUSE_PRESSED)
5526                  oldID = Event.MOUSE_DOWN;
5527                else if (id == MouseEvent.MOUSE_RELEASED)
5528                  oldID = Event.MOUSE_UP;
5529                else if (id == MouseEvent.MOUSE_MOVED)
5530                  oldID = Event.MOUSE_MOVE;
5531                else if (id == MouseEvent.MOUSE_DRAGGED)
5532                  oldID = Event.MOUSE_DRAG;
5533                else if (id == MouseEvent.MOUSE_ENTERED)
5534                  oldID = Event.MOUSE_ENTER;
5535                else if (id == MouseEvent.MOUSE_EXITED)
5536                  oldID = Event.MOUSE_EXIT;
5537                else
5538                  // No analogous AWT 1.0 mouse event.
5539                  return null;
5540    
5541                MouseEvent me = (MouseEvent) e;
5542    
5543                translated = new Event (target, when, oldID,
5544                                        me.getX (), me.getY (), 0, oldMods);
5545              }
5546            else if (e instanceof KeyEvent)
5547              {
5548                if (id == KeyEvent.KEY_PRESSED)
5549                  oldID = Event.KEY_PRESS;
5550                else if (e.getID () == KeyEvent.KEY_RELEASED)
5551                  oldID = Event.KEY_RELEASE;
5552                else
5553                  // No analogous AWT 1.0 key event.
5554                  return null;
5555    
5556                int oldKey = 0;
5557                int newKey = ((KeyEvent) e).getKeyCode ();
5558                switch (newKey)
5559                  {
5560                  case KeyEvent.VK_BACK_SPACE:
5561                    oldKey = Event.BACK_SPACE;
5562                    break;
5563                  case KeyEvent.VK_CAPS_LOCK:
5564                    oldKey = Event.CAPS_LOCK;
5565                    break;
5566                  case KeyEvent.VK_DELETE:
5567                    oldKey = Event.DELETE;
5568                    break;
5569                  case KeyEvent.VK_DOWN:
5570                  case KeyEvent.VK_KP_DOWN:
5571                    oldKey = Event.DOWN;
5572                    break;
5573                  case KeyEvent.VK_END:
5574                    oldKey = Event.END;
5575                    break;
5576                  case KeyEvent.VK_ENTER:
5577                    oldKey = Event.ENTER;
5578                    break;
5579                  case KeyEvent.VK_ESCAPE:
5580                    oldKey = Event.ESCAPE;
5581                    break;
5582                  case KeyEvent.VK_F1:
5583                    oldKey = Event.F1;
5584                    break;
5585                  case KeyEvent.VK_F10:
5586                    oldKey = Event.F10;
5587                    break;
5588                  case KeyEvent.VK_F11:
5589                    oldKey = Event.F11;
5590                    break;
5591                  case KeyEvent.VK_F12:
5592                    oldKey = Event.F12;
5593                    break;
5594                  case KeyEvent.VK_F2:
5595                    oldKey = Event.F2;
5596                    break;
5597                  case KeyEvent.VK_F3:
5598                    oldKey = Event.F3;
5599                    break;
5600                  case KeyEvent.VK_F4:
5601                    oldKey = Event.F4;
5602                    break;
5603                  case KeyEvent.VK_F5:
5604                    oldKey = Event.F5;
5605                    break;
5606                  case KeyEvent.VK_F6:
5607                    oldKey = Event.F6;
5608                    break;
5609                  case KeyEvent.VK_F7:
5610                    oldKey = Event.F7;
5611                    break;
5612                  case KeyEvent.VK_F8:
5613                    oldKey = Event.F8;
5614                    break;
5615                  case KeyEvent.VK_F9:
5616                    oldKey = Event.F9;
5617                    break;
5618                  case KeyEvent.VK_HOME:
5619                    oldKey = Event.HOME;
5620                    break;
5621                  case KeyEvent.VK_INSERT:
5622                    oldKey = Event.INSERT;
5623                    break;
5624                  case KeyEvent.VK_LEFT:
5625                  case KeyEvent.VK_KP_LEFT:
5626                    oldKey = Event.LEFT;
5627                    break;
5628                  case KeyEvent.VK_NUM_LOCK:
5629                    oldKey = Event.NUM_LOCK;
5630                    break;
5631                  case KeyEvent.VK_PAUSE:
5632                    oldKey = Event.PAUSE;
5633                    break;
5634                  case KeyEvent.VK_PAGE_DOWN:
5635                    oldKey = Event.PGDN;
5636                    break;
5637                  case KeyEvent.VK_PAGE_UP:
5638                    oldKey = Event.PGUP;
5639                    break;
5640                  case KeyEvent.VK_PRINTSCREEN:
5641                    oldKey = Event.PRINT_SCREEN;
5642                    break;
5643                  case KeyEvent.VK_RIGHT:
5644                  case KeyEvent.VK_KP_RIGHT:
5645                    oldKey = Event.RIGHT;
5646                    break;
5647                  case KeyEvent.VK_SCROLL_LOCK:
5648                    oldKey = Event.SCROLL_LOCK;
5649                    break;
5650                  case KeyEvent.VK_TAB:
5651                    oldKey = Event.TAB;
5652                    break;
5653                  case KeyEvent.VK_UP:
5654                  case KeyEvent.VK_KP_UP:
5655                    oldKey = Event.UP;
5656                    break;
5657                  default:
5658                    oldKey = ((KeyEvent) e).getKeyChar();
5659                  }
5660    
5661                translated = new Event (target, when, oldID,
5662                                        0, 0, oldKey, oldMods);
5663              }
5664          }
5665        else if (e instanceof AdjustmentEvent)
5666          {
5667            AdjustmentEvent ae = (AdjustmentEvent) e;
5668            int type = ae.getAdjustmentType();
5669            int oldType;
5670            if (type == AdjustmentEvent.BLOCK_DECREMENT)
5671              oldType = Event.SCROLL_PAGE_UP;
5672            else if (type == AdjustmentEvent.BLOCK_INCREMENT)
5673              oldType = Event.SCROLL_PAGE_DOWN;
5674            else if (type == AdjustmentEvent.TRACK)
5675              oldType = Event.SCROLL_ABSOLUTE;
5676            else if (type == AdjustmentEvent.UNIT_DECREMENT)
5677              oldType = Event.SCROLL_LINE_UP;
5678            else if (type == AdjustmentEvent.UNIT_INCREMENT)
5679              oldType = Event.SCROLL_LINE_DOWN;
5680            else
5681              oldType = type;
5682            translated = new Event(target, oldType, new Integer(ae.getValue()));
5683          }
5684        else if (e instanceof ActionEvent)
5685          translated = new Event (target, Event.ACTION_EVENT,
5686                                  ((ActionEvent) e).getActionCommand ());
5687    
5688        return translated;
5689      }
5690    
5691      /**
5692       * Implementation of dispatchEvent. Allows trusted package classes
5693       * to dispatch additional events first.  This implementation first
5694       * translates <code>e</code> to an AWT 1.0 event and sends the
5695       * result to {@link #postEvent}.  If the AWT 1.0 event is not
5696       * handled, and events of type <code>e</code> are enabled for this
5697       * component, e is passed on to {@link #processEvent}.
5698       *
5699       * @param e the event to dispatch
5700       */
5701      void dispatchEventImpl(AWTEvent e)
5702      {
5703        // Update the component's knowledge about the size.
5704        // Important: Please look at the big comment in ComponentReshapeEvent
5705        // to learn why we did it this way. If you change this code, make
5706        // sure that the peer->AWT bounds update still works.
5707        // (for instance: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29448 )
5708        if (e instanceof ComponentReshapeEvent)
5709          {
5710            ComponentReshapeEvent reshape = (ComponentReshapeEvent) e;
5711            x = reshape.x;
5712            y = reshape.y;
5713            width = reshape.width;
5714            height = reshape.height;
5715            return;
5716          }
5717    
5718        // Retarget focus events before dispatching it to the KeyboardFocusManager
5719        // in order to handle lightweight components properly.
5720        boolean dispatched = false;
5721        if (! e.isFocusManagerEvent)
5722          {
5723            e = KeyboardFocusManager.retargetFocusEvent(e);
5724            dispatched = KeyboardFocusManager.getCurrentKeyboardFocusManager()
5725                                              .dispatchEvent(e);
5726          }
5727    
5728        if (! dispatched)
5729          {
5730            // Give toolkit a chance to dispatch the event
5731            // to globally registered listeners.
5732            Toolkit.getDefaultToolkit().globalDispatchEvent(e);
5733    
5734            if (newEventsOnly)
5735              {
5736                if (eventTypeEnabled(e.id))
5737                  processEvent(e);
5738              }
5739            else
5740              {
5741                Event oldEvent = translateEvent(e);
5742                if (oldEvent != null)
5743                  postEvent (oldEvent);
5744              }
5745            if (peer != null)
5746              peer.handleEvent(e);
5747          }
5748      }
5749    
5750      /**
5751       * Tells whether or not an event type is enabled.
5752       */
5753      boolean eventTypeEnabled (int type)
5754      {
5755        if (type > AWTEvent.RESERVED_ID_MAX)
5756          return true;
5757    
5758        switch (type)
5759          {
5760          case HierarchyEvent.HIERARCHY_CHANGED:
5761            return (hierarchyListener != null 
5762                || (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) != 0);
5763            
5764          case HierarchyEvent.ANCESTOR_MOVED:
5765          case HierarchyEvent.ANCESTOR_RESIZED:
5766            return (hierarchyBoundsListener != null 
5767                || (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0);
5768            
5769          case ComponentEvent.COMPONENT_HIDDEN:
5770          case ComponentEvent.COMPONENT_MOVED:
5771          case ComponentEvent.COMPONENT_RESIZED:
5772          case ComponentEvent.COMPONENT_SHOWN:
5773            return (componentListener != null
5774                    || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0);
5775    
5776          case KeyEvent.KEY_PRESSED:
5777          case KeyEvent.KEY_RELEASED:
5778          case KeyEvent.KEY_TYPED:
5779            return (keyListener != null
5780                    || (eventMask & AWTEvent.KEY_EVENT_MASK) != 0);
5781    
5782          case MouseEvent.MOUSE_CLICKED:
5783          case MouseEvent.MOUSE_ENTERED:
5784          case MouseEvent.MOUSE_EXITED:
5785          case MouseEvent.MOUSE_PRESSED:
5786          case MouseEvent.MOUSE_RELEASED:
5787            return (mouseListener != null
5788                    || (eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0);
5789          case MouseEvent.MOUSE_MOVED:
5790          case MouseEvent.MOUSE_DRAGGED:
5791            return (mouseMotionListener != null
5792                    || (eventMask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 0);
5793          case MouseEvent.MOUSE_WHEEL:
5794            return (mouseWheelListener != null
5795                    || (eventMask & AWTEvent.MOUSE_WHEEL_EVENT_MASK) != 0);
5796            
5797          case FocusEvent.FOCUS_GAINED:
5798          case FocusEvent.FOCUS_LOST:
5799            return (focusListener != null
5800                    || (eventMask & AWTEvent.FOCUS_EVENT_MASK) != 0);
5801    
5802          case InputMethodEvent.INPUT_METHOD_TEXT_CHANGED:
5803          case InputMethodEvent.CARET_POSITION_CHANGED:
5804            return (inputMethodListener != null
5805                    || (eventMask & AWTEvent.INPUT_METHOD_EVENT_MASK) != 0);
5806            
5807          case PaintEvent.PAINT:
5808          case PaintEvent.UPDATE:
5809            return (eventMask & AWTEvent.PAINT_EVENT_MASK) != 0;
5810            
5811          default:
5812            return false;
5813          }
5814      }
5815    
5816      /**
5817       * Returns <code>true</code> when this component and all of its ancestors
5818       * are visible, <code>false</code> otherwise.
5819       *
5820       * @return <code>true</code> when this component and all of its ancestors
5821       *         are visible, <code>false</code> otherwise
5822       */
5823      boolean isHierarchyVisible()
5824      {
5825        boolean visible = isVisible();
5826        Component comp = parent;
5827        while (comp != null && visible)
5828          {
5829            comp = comp.parent;
5830            if (comp != null)
5831              visible = visible && comp.isVisible();
5832          }
5833        return visible;
5834      }
5835    
5836      /**
5837       * Returns the mouse pointer position relative to this Component's
5838       * top-left corner.
5839       *
5840       * @return relative mouse pointer position
5841       *
5842       * @throws HeadlessException if in a headless environment
5843       */
5844      public Point getMousePosition() throws HeadlessException
5845      {
5846        return getMousePositionHelper(true);
5847      }
5848    
5849      Point getMousePositionHelper(boolean allowChildren) throws HeadlessException
5850      {
5851        if (GraphicsEnvironment.isHeadless())
5852          throw new HeadlessException("can't get mouse position"
5853                                      + " in headless environment");
5854        if (!isShowing())
5855          return null;
5856    
5857        Component parent = this;
5858        int windowRelativeXOffset = 0;
5859        int windowRelativeYOffset = 0;
5860        while (parent != null && !(parent instanceof Window))
5861          {
5862            windowRelativeXOffset += parent.getX();
5863            windowRelativeYOffset += parent.getY();
5864            parent = parent.getParent();
5865          }
5866        if (parent == null)
5867          return null;
5868    
5869        Window window = (Window) parent;
5870        if (!Toolkit.getDefaultToolkit()
5871            .getMouseInfoPeer().isWindowUnderMouse(window))
5872          return null;
5873    
5874        PointerInfo info = MouseInfo.getPointerInfo();
5875        Point mouseLocation = info.getLocation();
5876        Point windowLocation = window.getLocationOnScreen();
5877    
5878        int x = mouseLocation.x - windowLocation.x;
5879        int y = mouseLocation.y - windowLocation.y;
5880    
5881        if (!mouseOverComponent(window.getComponentAt(x, y), allowChildren))
5882          return null;
5883    
5884        return new Point(x - windowRelativeXOffset, y - windowRelativeYOffset);
5885      }
5886    
5887      boolean mouseOverComponent(Component component, boolean allowChildren)
5888      {
5889        return component == this;
5890      }
5891    
5892      /**
5893       * This method is used to implement transferFocus(). CHILD is the child
5894       * making the request. This is overridden by Container; when called for an
5895       * ordinary component there is no child and so we always return null.
5896       *
5897       * FIXME: is this still needed, in light of focus traversal policies?
5898       *
5899       * @param child the component making the request
5900       * @return the next component to focus on
5901       */
5902      Component findNextFocusComponent(Component child)
5903      {
5904        return null;
5905      }
5906    
5907      /**
5908       * Deserializes this component. This regenerates all serializable listeners
5909       * which were registered originally.
5910       *
5911       * @param s the stream to read from
5912       * @throws ClassNotFoundException if deserialization fails
5913       * @throws IOException if the stream fails
5914       */
5915      private void readObject(ObjectInputStream s)
5916        throws ClassNotFoundException, IOException
5917      {
5918        s.defaultReadObject();
5919        String key = (String) s.readObject();
5920        while (key != null)
5921          {
5922            Object listener = s.readObject();
5923            if ("componentL".equals(key))
5924              addComponentListener((ComponentListener) listener);
5925            else if ("focusL".equals(key))
5926              addFocusListener((FocusListener) listener);
5927            else if ("keyL".equals(key))
5928              addKeyListener((KeyListener) listener);
5929            else if ("mouseL".equals(key))
5930              addMouseListener((MouseListener) listener);
5931            else if ("mouseMotionL".equals(key))
5932              addMouseMotionListener((MouseMotionListener) listener);
5933            else if ("inputMethodL".equals(key))
5934              addInputMethodListener((InputMethodListener) listener);
5935            else if ("hierarchyL".equals(key))
5936              addHierarchyListener((HierarchyListener) listener);
5937            else if ("hierarchyBoundsL".equals(key))
5938              addHierarchyBoundsListener((HierarchyBoundsListener) listener);
5939            else if ("mouseWheelL".equals(key))
5940              addMouseWheelListener((MouseWheelListener) listener);
5941            key = (String) s.readObject();
5942          }
5943      }
5944    
5945      /**
5946       * Serializes this component. This ignores all listeners which do not
5947       * implement Serializable, but includes those that do.
5948       *
5949       * @param s the stream to write to
5950       * @throws IOException if the stream fails
5951       */
5952      private void writeObject(ObjectOutputStream s) throws IOException
5953      {
5954        s.defaultWriteObject();
5955        AWTEventMulticaster.save(s, "componentL", componentListener);
5956        AWTEventMulticaster.save(s, "focusL", focusListener);
5957        AWTEventMulticaster.save(s, "keyL", keyListener);
5958        AWTEventMulticaster.save(s, "mouseL", mouseListener);
5959        AWTEventMulticaster.save(s, "mouseMotionL", mouseMotionListener);
5960        AWTEventMulticaster.save(s, "inputMethodL", inputMethodListener);
5961        AWTEventMulticaster.save(s, "hierarchyL", hierarchyListener);
5962        AWTEventMulticaster.save(s, "hierarchyBoundsL", hierarchyBoundsListener);
5963        AWTEventMulticaster.save(s, "mouseWheelL", mouseWheelListener);
5964        s.writeObject(null);
5965      }
5966    
5967      
5968      // Nested classes.
5969      
5970      /**
5971       * This class fixes the bounds for a Heavyweight component that
5972       * is placed inside a Lightweight container. When the lightweight is
5973       * moved or resized, setBounds for the lightweight peer does nothing.
5974       * Therefore, it was never moved on the screen. This class is 
5975       * attached to the lightweight, and it adjusts the position and size
5976       * of the peer when notified.
5977       * This is the same for show and hide.
5978       */
5979      class HeavyweightInLightweightListener
5980          implements ComponentListener
5981      {
5982        
5983        /**
5984         * Constructor. Adds component listener to lightweight parent.
5985         * 
5986         * @param parent - the lightweight container.
5987         */
5988        public HeavyweightInLightweightListener(Container parent)
5989        {
5990          parent.addComponentListener(this);
5991        }
5992        
5993        /**
5994         * This method is called when the component is resized.
5995         * 
5996         * @param event the <code>ComponentEvent</code> indicating the resize
5997         */
5998        public void componentResized(ComponentEvent event)
5999        {
6000          // Nothing to do here, componentMoved will be called.
6001        }
6002    
6003        /**
6004         * This method is called when the component is moved.
6005         * 
6006         * @param event the <code>ComponentEvent</code> indicating the move
6007         */
6008        public void componentMoved(ComponentEvent event)
6009        {
6010          if (peer != null)
6011            peer.setBounds(x, y, width, height);
6012        }
6013    
6014        /**
6015         * This method is called when the component is made visible.
6016         * 
6017         * @param event the <code>ComponentEvent</code> indicating the visibility
6018         */
6019        public void componentShown(ComponentEvent event)
6020        {
6021          if (isShowing())
6022            peer.show();
6023        }
6024    
6025        /**
6026         * This method is called when the component is hidden.
6027         * 
6028         * @param event the <code>ComponentEvent</code> indicating the visibility
6029         */
6030        public void componentHidden(ComponentEvent event)
6031        {
6032          if (isShowing())
6033            peer.hide();
6034        }
6035      }
6036      
6037      /**
6038       * This class provides accessibility support for subclasses of container.
6039       *
6040       * @author Eric Blake (ebb9@email.byu.edu)
6041       * @since 1.3
6042       * @status updated to 1.4
6043       */
6044      protected abstract class AccessibleAWTComponent extends AccessibleContext
6045        implements Serializable, AccessibleComponent
6046      {
6047        /**
6048         * Compatible with JDK 1.3+.
6049         */
6050        private static final long serialVersionUID = 642321655757800191L;
6051    
6052        /**
6053         * Converts show/hide events to PropertyChange events, and is registered
6054         * as a component listener on this component.
6055         *
6056         * @serial the component handler
6057         */
6058        protected ComponentListener accessibleAWTComponentHandler
6059          = new AccessibleAWTComponentHandler();
6060    
6061        /**
6062         * Converts focus events to PropertyChange events, and is registered
6063         * as a focus listener on this component.
6064         *
6065         * @serial the focus handler
6066         */
6067        protected FocusListener accessibleAWTFocusHandler
6068          = new AccessibleAWTFocusHandler();
6069    
6070        /**
6071         * The default constructor.
6072         */
6073        protected AccessibleAWTComponent()
6074        {
6075          Component.this.addComponentListener(accessibleAWTComponentHandler);
6076          Component.this.addFocusListener(accessibleAWTFocusHandler);
6077        }
6078    
6079        /**
6080         * Adds a global property change listener to the accessible component.
6081         *
6082         * @param l the listener to add
6083         * @see #ACCESSIBLE_NAME_PROPERTY
6084         * @see #ACCESSIBLE_DESCRIPTION_PROPERTY
6085         * @see #ACCESSIBLE_STATE_PROPERTY
6086         * @see #ACCESSIBLE_VALUE_PROPERTY
6087         * @see #ACCESSIBLE_SELECTION_PROPERTY
6088         * @see #ACCESSIBLE_TEXT_PROPERTY
6089         * @see #ACCESSIBLE_VISIBLE_DATA_PROPERTY
6090         */
6091        public void addPropertyChangeListener(PropertyChangeListener l)
6092        {
6093          Component.this.addPropertyChangeListener(l);
6094          super.addPropertyChangeListener(l);
6095        }
6096    
6097        /**
6098         * Removes a global property change listener from this accessible
6099         * component.
6100         *
6101         * @param l the listener to remove
6102         */
6103        public void removePropertyChangeListener(PropertyChangeListener l)
6104        {
6105          Component.this.removePropertyChangeListener(l);
6106          super.removePropertyChangeListener(l);
6107        }
6108    
6109        /**
6110         * Returns the accessible name of this component. It is almost always
6111         * wrong to return getName(), since it is not localized. In fact, for
6112         * things like buttons, this should be the text of the button, not the
6113         * name of the object. The tooltip text might also be appropriate.
6114         *
6115         * @return the name
6116         * @see #setAccessibleName(String)
6117         */
6118        public String getAccessibleName()
6119        {
6120          return accessibleName;
6121        }
6122    
6123        /**
6124         * Returns a brief description of this accessible context. This should
6125         * be localized.
6126         *
6127         * @return a description of this component
6128         * @see #setAccessibleDescription(String)
6129         */
6130        public String getAccessibleDescription()
6131        {
6132          return accessibleDescription;
6133        }
6134    
6135        /**
6136         * Returns the role of this component.
6137         *
6138         * @return the accessible role
6139         */
6140        public AccessibleRole getAccessibleRole()
6141        {
6142          return AccessibleRole.AWT_COMPONENT;
6143        }
6144    
6145        /**
6146         * Returns a state set describing this component's state.
6147         *
6148         * @return a new state set
6149         * @see AccessibleState
6150         */
6151        public AccessibleStateSet getAccessibleStateSet()
6152        {
6153          AccessibleStateSet s = new AccessibleStateSet();
6154          if (Component.this.isEnabled())
6155            s.add(AccessibleState.ENABLED);
6156          if (isFocusable())
6157            s.add(AccessibleState.FOCUSABLE);
6158          if (isFocusOwner())
6159            s.add(AccessibleState.FOCUSED);
6160          // Note: While the java.awt.Component has an 'opaque' property, it
6161          // seems that it is not added to the accessible state set here, even
6162          // if this property is true. However, it is handled for
6163          // javax.swing.JComponent, so we add it there.
6164          if (Component.this.isShowing())
6165            s.add(AccessibleState.SHOWING);
6166          if (Component.this.isVisible())
6167            s.add(AccessibleState.VISIBLE);
6168          return s;
6169        }
6170    
6171        /**
6172         * Returns the parent of this component, if it is accessible.
6173         *
6174         * @return the accessible parent
6175         */
6176        public Accessible getAccessibleParent()
6177        {
6178          if (accessibleParent == null)
6179            {
6180              Container parent = getParent();
6181              accessibleParent = parent instanceof Accessible
6182                ? (Accessible) parent : null;
6183            }
6184          return accessibleParent;
6185        }
6186    
6187        /**
6188         * Returns the index of this component in its accessible parent.
6189         *
6190         * @return the index, or -1 if the parent is not accessible
6191         * @see #getAccessibleParent()
6192         */
6193        public int getAccessibleIndexInParent()
6194        {
6195          if (getAccessibleParent() == null)
6196            return -1;
6197          AccessibleContext context
6198            = ((Component) accessibleParent).getAccessibleContext();
6199          if (context == null)
6200            return -1;
6201          for (int i = context.getAccessibleChildrenCount(); --i >= 0; )
6202            if (context.getAccessibleChild(i) == Component.this)
6203              return i;
6204          return -1;
6205        }
6206    
6207        /**
6208         * Returns the number of children of this component which implement
6209         * Accessible. Subclasses must override this if they can have children.
6210         *
6211         * @return the number of accessible children, default 0
6212         */
6213        public int getAccessibleChildrenCount()
6214        {
6215          return 0;
6216        }
6217    
6218        /**
6219         * Returns the ith accessible child. Subclasses must override this if
6220         * they can have children.
6221         *
6222         * @return the ith accessible child, or null
6223         * @see #getAccessibleChildrenCount()
6224         */
6225        public Accessible getAccessibleChild(int i)
6226        {
6227          return null;
6228        }
6229    
6230        /**
6231         * Returns the locale of this component.
6232         *
6233         * @return the locale
6234         * @throws IllegalComponentStateException if the locale is unknown
6235         */
6236        public Locale getLocale()
6237        {
6238          return Component.this.getLocale();
6239        }
6240    
6241        /**
6242         * Returns this, since it is an accessible component.
6243         *
6244         * @return the accessible component
6245         */
6246        public AccessibleComponent getAccessibleComponent()
6247        {
6248          return this;
6249        }
6250    
6251        /**
6252         * Gets the background color.
6253         *
6254         * @return the background color
6255         * @see #setBackground(Color)
6256         */
6257        public Color getBackground()
6258        {
6259          return Component.this.getBackground();
6260        }
6261    
6262        /**
6263         * Sets the background color.
6264         *
6265         * @param c the background color
6266         * @see #getBackground()
6267         * @see #isOpaque()
6268         */
6269        public void setBackground(Color c)
6270        {
6271          Component.this.setBackground(c);
6272        }
6273    
6274        /**
6275         * Gets the foreground color.
6276         *
6277         * @return the foreground color
6278         * @see #setForeground(Color)
6279         */
6280        public Color getForeground()
6281        {
6282          return Component.this.getForeground();
6283        }
6284    
6285        /**
6286         * Sets the foreground color.
6287         *
6288         * @param c the foreground color
6289         * @see #getForeground()
6290         */
6291        public void setForeground(Color c)
6292        {
6293          Component.this.setForeground(c);
6294        }
6295    
6296        /**
6297         * Gets the cursor.
6298         *
6299         * @return the cursor
6300         * @see #setCursor(Cursor)
6301         */
6302        public Cursor getCursor()
6303        {
6304          return Component.this.getCursor();
6305        }
6306    
6307        /**
6308         * Sets the cursor.
6309         *
6310         * @param cursor the cursor
6311         * @see #getCursor()
6312         */
6313        public void setCursor(Cursor cursor)
6314        {
6315          Component.this.setCursor(cursor);
6316        }
6317    
6318        /**
6319         * Gets the font.
6320         *
6321         * @return the font
6322         * @see #setFont(Font)
6323         */
6324        public Font getFont()
6325        {
6326          return Component.this.getFont();
6327        }
6328    
6329        /**
6330         * Sets the font.
6331         *
6332         * @param f the font
6333         * @see #getFont()
6334         */
6335        public void setFont(Font f)
6336        {
6337          Component.this.setFont(f);
6338        }
6339    
6340        /**
6341         * Gets the font metrics for a font.
6342         *
6343         * @param f the font to look up
6344         * @return its metrics
6345         * @throws NullPointerException if f is null
6346         * @see #getFont()
6347         */
6348        public FontMetrics getFontMetrics(Font f)
6349        {
6350          return Component.this.getFontMetrics(f);
6351        }
6352    
6353        /**
6354         * Tests if the component is enabled.
6355         *
6356         * @return true if the component is enabled
6357         * @see #setEnabled(boolean)
6358         * @see #getAccessibleStateSet()
6359         * @see AccessibleState#ENABLED
6360         */
6361        public boolean isEnabled()
6362        {
6363          return Component.this.isEnabled();
6364        }
6365    
6366        /**
6367         * Set whether the component is enabled.
6368         *
6369         * @param b the new enabled status
6370         * @see #isEnabled()
6371         */
6372        public void setEnabled(boolean b)
6373        {
6374          Component.this.setEnabled(b);
6375        }
6376    
6377        /**
6378         * Test whether the component is visible (not necesarily showing).
6379         *
6380         * @return true if it is visible
6381         * @see #setVisible(boolean)
6382         * @see #getAccessibleStateSet()
6383         * @see AccessibleState#VISIBLE
6384         */
6385        public boolean isVisible()
6386        {
6387          return Component.this.isVisible();
6388        }
6389    
6390        /**
6391         * Sets the visibility of this component.
6392         *
6393         * @param b the desired visibility
6394         * @see #isVisible()
6395         */
6396        public void setVisible(boolean b)
6397        {
6398          Component.this.setVisible(b);
6399        }
6400    
6401        /**
6402         * Tests if the component is showing.
6403         *
6404         * @return true if this is showing
6405         */
6406        public boolean isShowing()
6407        {
6408          return Component.this.isShowing();
6409        }
6410    
6411        /**
6412         * Tests if the point is contained in this component.
6413         *
6414         * @param p the point to check
6415         * @return true if it is contained
6416         * @throws NullPointerException if p is null
6417         */
6418        public boolean contains(Point p)
6419        {
6420          return Component.this.contains(p.x, p.y);
6421        }
6422    
6423        /**
6424         * Returns the location of this object on the screen, or null if it is
6425         * not showing.
6426         *
6427         * @return the location relative to screen coordinates, if showing
6428         * @see #getBounds()
6429         * @see #getLocation()
6430         */
6431        public Point getLocationOnScreen()
6432        {
6433          return Component.this.isShowing() ? Component.this.getLocationOnScreen()
6434            : null;
6435        }
6436    
6437        /**
6438         * Returns the location of this object relative to its parent's coordinate
6439         * system, or null if it is not showing.
6440         *
6441         * @return the location
6442         * @see #getBounds()
6443         * @see #getLocationOnScreen()
6444         */
6445        public Point getLocation()
6446        {
6447          return Component.this.getLocation();
6448        }
6449    
6450        /**
6451         * Sets the location of this relative to its parent's coordinate system.
6452         *
6453         * @param p the location
6454         * @throws NullPointerException if p is null
6455         * @see #getLocation()
6456         */
6457        public void setLocation(Point p)
6458        {
6459          Component.this.setLocation(p.x, p.y);
6460        }
6461    
6462        /**
6463         * Gets the bounds of this component, or null if it is not on screen.
6464         *
6465         * @return the bounds
6466         * @see #contains(Point)
6467         * @see #setBounds(Rectangle)
6468         */
6469        public Rectangle getBounds()
6470        {
6471          return Component.this.getBounds();
6472        }
6473    
6474        /**
6475         * Sets the bounds of this component.
6476         *
6477         * @param r the bounds
6478         * @throws NullPointerException if r is null
6479         * @see #getBounds()
6480         */
6481        public void setBounds(Rectangle r)
6482        {
6483          Component.this.setBounds(r.x, r.y, r.width, r.height);
6484        }
6485    
6486        /**
6487         * Gets the size of this component, or null if it is not showing.
6488         *
6489         * @return the size
6490         * @see #setSize(Dimension)
6491         */
6492        public Dimension getSize()
6493        {
6494          return Component.this.getSize();
6495        }
6496    
6497        /**
6498         * Sets the size of this component.
6499         *
6500         * @param d the size
6501         * @throws NullPointerException if d is null
6502         * @see #getSize()
6503         */
6504        public void setSize(Dimension d)
6505        {
6506          Component.this.setSize(d.width, d.height);
6507        }
6508    
6509        /**
6510         * Returns the Accessible child at a point relative to the coordinate
6511         * system of this component, if one exists, or null. Since components
6512         * have no children, subclasses must override this to get anything besides
6513         * null.
6514         *
6515         * @param p the point to check
6516         * @return the accessible child at that point
6517         * @throws NullPointerException if p is null
6518         */
6519        public Accessible getAccessibleAt(Point p)
6520        {
6521          return null;
6522        }
6523    
6524        /**
6525         * Tests whether this component can accept focus.
6526         *
6527         * @return true if this is focus traversable
6528         * @see #getAccessibleStateSet ()
6529         * @see AccessibleState#FOCUSABLE
6530         * @see AccessibleState#FOCUSED
6531         */
6532        public boolean isFocusTraversable ()
6533        {
6534          return Component.this.isFocusTraversable ();
6535        }
6536    
6537        /**
6538         * Requests focus for this component.
6539         *
6540         * @see #isFocusTraversable ()
6541         */
6542        public void requestFocus ()
6543        {
6544          Component.this.requestFocus ();
6545        }
6546    
6547        /**
6548         * Adds a focus listener.
6549         *
6550         * @param l the listener to add
6551         */
6552        public void addFocusListener(FocusListener l)
6553        {
6554          Component.this.addFocusListener(l);
6555        }
6556    
6557        /**
6558         * Removes a focus listener.
6559         *
6560         * @param l the listener to remove
6561         */
6562        public void removeFocusListener(FocusListener l)
6563        {
6564          Component.this.removeFocusListener(l);
6565        }
6566    
6567        /**
6568         * Converts component changes into property changes.
6569         *
6570         * @author Eric Blake (ebb9@email.byu.edu)
6571         * @since 1.3
6572         * @status updated to 1.4
6573         */
6574        protected class AccessibleAWTComponentHandler implements ComponentListener
6575        {
6576          /**
6577           * Default constructor.
6578           */
6579          protected AccessibleAWTComponentHandler()
6580          {
6581            // Nothing to do here.
6582          }
6583    
6584          /**
6585           * Convert a component hidden to a property change.
6586           *
6587           * @param e the event to convert
6588           */
6589          public void componentHidden(ComponentEvent e)
6590          {
6591            AccessibleAWTComponent.this.firePropertyChange
6592              (ACCESSIBLE_STATE_PROPERTY, AccessibleState.VISIBLE, null);
6593          }
6594    
6595          /**
6596           * Convert a component shown to a property change.
6597           *
6598           * @param e the event to convert
6599           */
6600          public void componentShown(ComponentEvent e)
6601          {
6602            AccessibleAWTComponent.this.firePropertyChange
6603              (ACCESSIBLE_STATE_PROPERTY, null, AccessibleState.VISIBLE);
6604          }
6605    
6606          /**
6607           * Moving a component does not affect properties.
6608           *
6609           * @param e ignored
6610           */
6611          public void componentMoved(ComponentEvent e)
6612          {
6613            // Nothing to do here.
6614          }
6615    
6616          /**
6617           * Resizing a component does not affect properties.
6618           *
6619           * @param e ignored
6620           */
6621          public void componentResized(ComponentEvent e)
6622          {
6623            // Nothing to do here.
6624          }
6625        } // class AccessibleAWTComponentHandler
6626    
6627        /**
6628         * Converts focus changes into property changes.
6629         *
6630         * @author Eric Blake (ebb9@email.byu.edu)
6631         * @since 1.3
6632         * @status updated to 1.4
6633         */
6634        protected class AccessibleAWTFocusHandler implements FocusListener
6635        {
6636          /**
6637           * Default constructor.
6638           */
6639          protected AccessibleAWTFocusHandler()
6640          {
6641            // Nothing to do here.
6642          }
6643    
6644          /**
6645           * Convert a focus gained to a property change.
6646           *
6647           * @param e the event to convert
6648           */
6649          public void focusGained(FocusEvent e)
6650          {
6651            AccessibleAWTComponent.this.firePropertyChange
6652              (ACCESSIBLE_STATE_PROPERTY, null, AccessibleState.FOCUSED);
6653          }
6654    
6655          /**
6656           * Convert a focus lost to a property change.
6657           *
6658           * @param e the event to convert
6659           */
6660          public void focusLost(FocusEvent e)
6661          {
6662            AccessibleAWTComponent.this.firePropertyChange
6663              (ACCESSIBLE_STATE_PROPERTY, AccessibleState.FOCUSED, null);
6664          }
6665        } // class AccessibleAWTComponentHandler
6666      } // class AccessibleAWTComponent
6667    
6668      /**
6669       * This class provides support for blitting offscreen surfaces to a
6670       * component.
6671       *
6672       * @see BufferStrategy
6673       *
6674       * @since 1.4
6675       */
6676      protected class BltBufferStrategy extends BufferStrategy
6677      {
6678        /**
6679         * The capabilities of the image buffer.
6680         */
6681        protected BufferCapabilities caps;
6682    
6683        /**
6684         * The back buffers used in this strategy.
6685         */
6686        protected VolatileImage[] backBuffers;
6687    
6688        /**
6689         * Whether or not the image buffer resources are allocated and
6690         * ready to be drawn into.
6691         */
6692        protected boolean validatedContents;
6693    
6694        /**
6695         * The width of the back buffers.
6696         */
6697        protected int width;
6698    
6699        /**
6700         * The height of the back buffers.
6701         */
6702        protected int height;
6703    
6704        /**
6705         * The front buffer.
6706         */
6707        private VolatileImage frontBuffer;
6708    
6709        /**
6710         * Creates a blitting buffer strategy.
6711         *
6712         * @param numBuffers the number of buffers, including the front
6713         * buffer
6714         * @param caps the capabilities of this strategy
6715         */
6716        protected BltBufferStrategy(int numBuffers, BufferCapabilities caps)
6717        {
6718          this.caps = caps;
6719          createBackBuffers(numBuffers - 1);
6720          width = getWidth();
6721          height = getHeight();
6722        }
6723    
6724        /**
6725         * Initializes the backBuffers field with an array of numBuffers
6726         * VolatileImages.
6727         *
6728         * @param numBuffers the number of backbuffers to create
6729         */
6730        protected void createBackBuffers(int numBuffers)
6731        {
6732          GraphicsConfiguration c =
6733            GraphicsEnvironment.getLocalGraphicsEnvironment()
6734            .getDefaultScreenDevice().getDefaultConfiguration();
6735    
6736          backBuffers = new VolatileImage[numBuffers];
6737    
6738          for (int i = 0; i < numBuffers; i++)
6739            backBuffers[i] = c.createCompatibleVolatileImage(width, height);
6740        }
6741    
6742        /**
6743         * Retrieves the capabilities of this buffer strategy.
6744         *
6745         * @return the capabilities of this buffer strategy
6746         */
6747        public BufferCapabilities getCapabilities()
6748        {
6749          return caps;
6750        }
6751    
6752        /**
6753         * Retrieves a graphics object that can be used to draw into this
6754         * strategy's image buffer.
6755         *
6756         * @return a graphics object
6757         */
6758        public Graphics getDrawGraphics()
6759        {
6760          // Return the backmost buffer's graphics.
6761          return backBuffers[0].getGraphics();
6762        }
6763    
6764        /**
6765         * Bring the contents of the back buffer to the front buffer.
6766         */
6767        public void show()
6768        {
6769          GraphicsConfiguration c =
6770            GraphicsEnvironment.getLocalGraphicsEnvironment()
6771            .getDefaultScreenDevice().getDefaultConfiguration();
6772    
6773          // draw the front buffer.
6774          getGraphics().drawImage(backBuffers[backBuffers.length - 1],
6775                                  width, height, null);
6776    
6777          BufferCapabilities.FlipContents f = getCapabilities().getFlipContents();
6778    
6779          // blit the back buffers.
6780          for (int i = backBuffers.length - 1; i > 0 ; i--)
6781            backBuffers[i] = backBuffers[i - 1];
6782    
6783          // create new backmost buffer.
6784          if (f == BufferCapabilities.FlipContents.UNDEFINED)
6785            backBuffers[0] = c.createCompatibleVolatileImage(width, height);
6786    
6787          // create new backmost buffer and clear it to the background
6788          // color.
6789          if (f == BufferCapabilities.FlipContents.BACKGROUND)
6790            {
6791              backBuffers[0] = c.createCompatibleVolatileImage(width, height);
6792              backBuffers[0].getGraphics().clearRect(0, 0, width, height);
6793            }
6794    
6795          // FIXME: set the backmost buffer to the prior contents of the
6796          // front buffer.  How do we retrieve the contents of the front
6797          // buffer?
6798          //
6799          //      if (f == BufferCapabilities.FlipContents.PRIOR)
6800    
6801          // set the backmost buffer to a copy of the new front buffer.
6802          if (f == BufferCapabilities.FlipContents.COPIED)
6803            backBuffers[0] = backBuffers[backBuffers.length - 1];
6804        }
6805    
6806        /**
6807         * Re-create the image buffer resources if they've been lost.
6808         */
6809        protected void revalidate()
6810        {
6811          GraphicsConfiguration c =
6812            GraphicsEnvironment.getLocalGraphicsEnvironment()
6813            .getDefaultScreenDevice().getDefaultConfiguration();
6814    
6815          for (int i = 0; i < backBuffers.length; i++)
6816            {
6817              int result = backBuffers[i].validate(c);
6818              if (result == VolatileImage.IMAGE_INCOMPATIBLE)
6819                backBuffers[i] = c.createCompatibleVolatileImage(width, height);
6820            }
6821          validatedContents = true;
6822        }
6823    
6824        /**
6825         * Returns whether or not the image buffer resources have been
6826         * lost.
6827         *
6828         * @return true if the resources have been lost, false otherwise
6829         */
6830        public boolean contentsLost()
6831        {
6832          for (int i = 0; i < backBuffers.length; i++)
6833            {
6834              if (backBuffers[i].contentsLost())
6835                {
6836                  validatedContents = false;
6837                  return true;
6838                }
6839            }
6840          // we know that the buffer resources are valid now because we
6841          // just checked them
6842          validatedContents = true;
6843          return false;
6844        }
6845    
6846        /**
6847         * Returns whether or not the image buffer resources have been
6848         * restored.
6849         *
6850         * @return true if the resources have been restored, false
6851         * otherwise
6852         */
6853        public boolean contentsRestored()
6854        {
6855          GraphicsConfiguration c =
6856            GraphicsEnvironment.getLocalGraphicsEnvironment()
6857            .getDefaultScreenDevice().getDefaultConfiguration();
6858    
6859          boolean imageRestored = false;
6860    
6861          for (int i = 0; i < backBuffers.length; i++)
6862            {
6863              int result = backBuffers[i].validate(c);
6864              if (result == VolatileImage.IMAGE_RESTORED)
6865                imageRestored = true;
6866              else if (result == VolatileImage.IMAGE_INCOMPATIBLE)
6867                return false;
6868            }
6869          // we know that the buffer resources are valid now because we
6870          // just checked them
6871          validatedContents = true;
6872          return imageRestored;
6873        }
6874      }
6875    
6876      /**
6877       * This class provides support for flipping component buffers. It
6878       * can only be used on Canvases and Windows.
6879       *
6880       * @since 1.4
6881       */
6882      protected class FlipBufferStrategy extends BufferStrategy
6883      {
6884        /**
6885         * The number of buffers.
6886         */
6887        protected int numBuffers;
6888    
6889        /**
6890         * The capabilities of this buffering strategy.
6891         */
6892        protected BufferCapabilities caps;
6893    
6894        /**
6895         * An Image reference to the drawing buffer.
6896         */
6897        protected Image drawBuffer;
6898    
6899        /**
6900         * A VolatileImage reference to the drawing buffer.
6901         */
6902        protected VolatileImage drawVBuffer;
6903    
6904        /**
6905         * Whether or not the image buffer resources are allocated and
6906         * ready to be drawn into.
6907         */
6908        protected boolean validatedContents;
6909    
6910        /**
6911         * The width of the back buffer.
6912         */
6913        private int width;
6914    
6915        /**
6916         * The height of the back buffer.
6917         */
6918        private int height;
6919    
6920        /**
6921         * Creates a flipping buffer strategy.  The only supported
6922         * strategy for FlipBufferStrategy itself is a double-buffer page
6923         * flipping strategy.  It forms the basis for more complex derived
6924         * strategies.
6925         *
6926         * @param numBuffers the number of buffers
6927         * @param caps the capabilities of this buffering strategy
6928         *
6929         * @throws AWTException if the requested
6930         * number-of-buffers/capabilities combination is not supported
6931         */
6932        protected FlipBufferStrategy(int numBuffers, BufferCapabilities caps)
6933          throws AWTException
6934        {
6935          this.caps = caps;
6936          width = getWidth();
6937          height = getHeight();
6938    
6939          if (numBuffers > 1)
6940            createBuffers(numBuffers, caps);
6941          else
6942            {
6943              drawVBuffer = peer.createVolatileImage(width, height);
6944              drawBuffer = drawVBuffer;
6945            }
6946        }
6947    
6948        /**
6949         * Creates a multi-buffer flipping strategy.  The number of
6950         * buffers must be greater than one and the buffer capabilities
6951         * must specify page flipping.
6952         *
6953         * @param numBuffers the number of flipping buffers; must be
6954         * greater than one
6955         * @param caps the buffering capabilities; caps.isPageFlipping()
6956         * must return true
6957         *
6958         * @throws IllegalArgumentException if numBuffers is not greater
6959         * than one or if the page flipping capability is not requested
6960         *
6961         * @throws AWTException if the requested flipping strategy is not
6962         * supported
6963         */
6964        protected void createBuffers(int numBuffers, BufferCapabilities caps)
6965          throws AWTException
6966        {
6967          if (numBuffers <= 1)
6968            throw new IllegalArgumentException("FlipBufferStrategy.createBuffers:"
6969                                               + " numBuffers must be greater than"
6970                                               + " one.");
6971    
6972          if (!caps.isPageFlipping())
6973            throw new IllegalArgumentException("FlipBufferStrategy.createBuffers:"
6974                                               + " flipping must be a specified"
6975                                               + " capability.");
6976    
6977          peer.createBuffers(numBuffers, caps);
6978        }
6979    
6980        /**
6981         * Return a direct reference to the back buffer image.
6982         *
6983         * @return a direct reference to the back buffer image.
6984         */
6985        protected Image getBackBuffer()
6986        {
6987          return peer.getBackBuffer();
6988        }
6989    
6990        /**
6991         * Perform a flip operation to transfer the contents of the back
6992         * buffer to the front buffer.
6993         */
6994        protected void flip(BufferCapabilities.FlipContents flipAction)
6995        {
6996          peer.flip(flipAction);
6997        }
6998    
6999        /**
7000         * Release the back buffer's resources.
7001         */
7002        protected void destroyBuffers()
7003        {
7004          peer.destroyBuffers();
7005        }
7006    
7007        /**
7008         * Retrieves the capabilities of this buffer strategy.
7009         *
7010         * @return the capabilities of this buffer strategy
7011         */
7012        public BufferCapabilities getCapabilities()
7013        {
7014          return caps;
7015        }
7016    
7017        /**
7018         * Retrieves a graphics object that can be used to draw into this
7019         * strategy's image buffer.
7020         *
7021         * @return a graphics object
7022         */
7023        public Graphics getDrawGraphics()
7024        {
7025          return drawVBuffer.getGraphics();
7026        }
7027    
7028        /**
7029         * Re-create the image buffer resources if they've been lost.
7030         */
7031        protected void revalidate()
7032        {
7033          GraphicsConfiguration c =
7034            GraphicsEnvironment.getLocalGraphicsEnvironment()
7035            .getDefaultScreenDevice().getDefaultConfiguration();
7036    
7037          if (drawVBuffer.validate(c) == VolatileImage.IMAGE_INCOMPATIBLE)
7038            drawVBuffer = peer.createVolatileImage(width, height);
7039          validatedContents = true;
7040        }
7041    
7042        /**
7043         * Returns whether or not the image buffer resources have been
7044         * lost.
7045         *
7046         * @return true if the resources have been lost, false otherwise
7047         */
7048        public boolean contentsLost()
7049        {
7050          if (drawVBuffer.contentsLost())
7051            {
7052              validatedContents = false;
7053              return true;
7054            }
7055          // we know that the buffer resources are valid now because we
7056          // just checked them
7057          validatedContents = true;
7058          return false;
7059        }
7060    
7061        /**
7062         * Returns whether or not the image buffer resources have been
7063         * restored.
7064         *
7065         * @return true if the resources have been restored, false
7066         * otherwise
7067         */
7068        public boolean contentsRestored()
7069        {
7070          GraphicsConfiguration c =
7071            GraphicsEnvironment.getLocalGraphicsEnvironment()
7072            .getDefaultScreenDevice().getDefaultConfiguration();
7073    
7074          int result = drawVBuffer.validate(c);
7075    
7076          boolean imageRestored = false;
7077    
7078          if (result == VolatileImage.IMAGE_RESTORED)
7079            imageRestored = true;
7080          else if (result == VolatileImage.IMAGE_INCOMPATIBLE)
7081            return false;
7082    
7083          // we know that the buffer resources are valid now because we
7084          // just checked them
7085          validatedContents = true;
7086          return imageRestored;
7087        }
7088    
7089        /**
7090         * Bring the contents of the back buffer to the front buffer.
7091         */
7092        public void show()
7093        {
7094          flip(caps.getFlipContents());
7095        }
7096      }
7097    }