001    /* Component.java -- a graphics component
002       Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2006
003       Free Software Foundation
004    
005    This file is part of GNU Classpath.
006    
007    GNU Classpath is free software; you can redistribute it and/or modify
008    it under the terms of the GNU General Public License as published by
009    the Free Software Foundation; either version 2, or (at your option)
010    any later version.
011    
012    GNU Classpath is distributed in the hope that it will be useful, but
013    WITHOUT ANY WARRANTY; without even the implied warranty of
014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015    General Public License for more details.
016    
017    You should have received a copy of the GNU General Public License
018    along with GNU Classpath; see the file COPYING.  If not, write to the
019    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
020    02110-1301 USA.
021    
022    Linking this library statically or dynamically with other modules is
023    making a combined work based on this library.  Thus, the terms and
024    conditions of the GNU General Public License cover the whole
025    combination.
026    
027    As a special exception, the copyright holders of this library give you
028    permission to link this library with independent modules to produce an
029    executable, regardless of the license terms of these independent
030    modules, and to copy and distribute the resulting executable under
031    terms of your choice, provided that you also meet, for each linked
032    independent module, the terms and conditions of the license of that
033    module.  An independent module is a module which is not derived from
034    or based on this library.  If you modify this library, you may extend
035    this exception to your version of the library, but you are not
036    obligated to do so.  If you do not wish to do so, delete this
037    exception statement from your version. */
038    
039    
040    package java.awt;
041    
042    //import gnu.java.awt.dnd.peer.gtk.GtkDropTargetContextPeer;
043    
044    import gnu.java.awt.ComponentReshapeEvent;
045    
046    import gnu.java.lang.CPStringBuilder;
047    
048    import java.awt.dnd.DropTarget;
049    import java.awt.event.ActionEvent;
050    import java.awt.event.AdjustmentEvent;
051    import java.awt.event.ComponentEvent;
052    import java.awt.event.ComponentListener;
053    import java.awt.event.FocusEvent;
054    import java.awt.event.FocusListener;
055    import java.awt.event.HierarchyBoundsListener;
056    import java.awt.event.HierarchyEvent;
057    import java.awt.event.HierarchyListener;
058    import java.awt.event.InputEvent;
059    import java.awt.event.InputMethodEvent;
060    import java.awt.event.InputMethodListener;
061    import java.awt.event.KeyEvent;
062    import java.awt.event.KeyListener;
063    import java.awt.event.MouseEvent;
064    import java.awt.event.MouseListener;
065    import java.awt.event.MouseMotionListener;
066    import java.awt.event.MouseWheelEvent;
067    import java.awt.event.MouseWheelListener;
068    import java.awt.event.PaintEvent;
069    import java.awt.event.WindowEvent;
070    import java.awt.im.InputContext;
071    import java.awt.im.InputMethodRequests;
072    import java.awt.image.BufferStrategy;
073    import java.awt.image.ColorModel;
074    import java.awt.image.ImageObserver;
075    import java.awt.image.ImageProducer;
076    import java.awt.image.VolatileImage;
077    import java.awt.peer.ComponentPeer;
078    import java.awt.peer.LightweightPeer;
079    import java.beans.PropertyChangeEvent;
080    import java.beans.PropertyChangeListener;
081    import java.beans.PropertyChangeSupport;
082    import java.io.IOException;
083    import java.io.ObjectInputStream;
084    import java.io.ObjectOutputStream;
085    import java.io.PrintStream;
086    import java.io.PrintWriter;
087    import java.io.Serializable;
088    import java.lang.reflect.Array;
089    import java.util.Collections;
090    import java.util.EventListener;
091    import java.util.HashSet;
092    import java.util.Iterator;
093    import java.util.Locale;
094    import java.util.Set;
095    import java.util.Vector;
096    
097    import javax.accessibility.Accessible;
098    import javax.accessibility.AccessibleComponent;
099    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    
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    
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    
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    
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    }