OSDN Git Service

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