OSDN Git Service

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