OSDN Git Service

8f79f8a1d6635be03ecbf1be4af17549d60d7a27
[pf3gnuchains/gcc-fork.git] / libjava / java / awt / Component.java
1 /* Copyright (C) 1999, 2000, 2001, 2002  Free Software Foundation
2
3 This file is part of GNU Classpath.
4
5 GNU Classpath is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 GNU Classpath is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNU Classpath; see the file COPYING.  If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA.
19
20 As a special exception, if you link this library with other files to
21 produce an executable, this library does not by itself cause the
22 resulting executable to be covered by the GNU General Public License.
23 This exception does not however invalidate any other reasons why the
24 executable file might be covered by the GNU General Public License. */
25
26 package java.awt;
27 import java.awt.event.*;
28 import java.awt.image.*;
29 import java.io.PrintStream;
30 import java.io.PrintWriter;
31 import java.lang.reflect.*;
32 import java.util.EventListener;
33 import java.util.Locale;
34 import java.util.ResourceBundle;
35 import java.util.Vector;
36 import java.awt.peer.ComponentPeer;
37 import java.awt.peer.LightweightPeer;
38 import java.beans.PropertyChangeSupport;
39 import java.beans.PropertyChangeListener;
40 // import javax.accessibility.AccessibleContext;
41
42 /**
43   * The root of all evil.
44   *
45   * Status: Incomplete. The event dispatch mechanism is implemented. All 
46   * other methods defined in the J2SE 1.3 API javadoc exist, but are mostly 
47   * incomplete or only stubs; except for methods relating to the Drag and Drop, 
48   * Input Method, and Accessibility frameworks: These methods are present but 
49   * commented out.
50   */
51 public abstract class Component implements ImageObserver, MenuContainer, 
52                                            java.io.Serializable
53 {
54   /**
55    * Constant returned by the <code>getAlignmentY</code> method to indicate
56    * that the component wishes to be aligned to the bottom relative to
57    * other components.
58    */
59   public static final float BOTTOM_ALIGNMENT = (float)1.0;
60
61   /**
62    * Constant returned by the <code>getAlignmentY</code> and 
63    * <code>getAlignmentX</code> methods to indicate
64    * that the component wishes to be aligned to the center relative to
65    * other components.
66    */
67   public static final float CENTER_ALIGNMENT = (float)0.5;
68
69   /**
70    * Constant returned by the <code>getAlignmentY</code> method to indicate
71    * that the component wishes to be aligned to the top relative to
72    * other components.
73    */
74   public static final float TOP_ALIGNMENT = (float)0.0;
75
76   /**
77    * Constant returned by the <code>getAlignmentX</code> method to indicate
78    * that the component wishes to be aligned to the right relative to
79    * other components.
80    */
81   public static final float RIGHT_ALIGNMENT = (float)1.0;
82
83   /**
84    * Constant returned by the <code>getAlignmentX</code> method to indicate
85    * that the component wishes to be aligned to the left relative to
86    * other components.
87    */
88   public static final float LEFT_ALIGNMENT = (float)0.0;
89
90   /* Make the treelock a String so that it can easily be identified
91      in debug dumps. We clone the String in order to avoid a conflict in 
92      the unlikely event that some other package uses exactly the same string
93      as a lock object. */
94   static Object treeLock = new String("AWT_TREE_LOCK");
95
96   /* Serialized fields from the serialization spec. */
97   // FIXME: Default values?
98   int x;
99   int y;
100   int width;
101   int height;
102   Color foreground;
103   Color background;
104   Font font;
105   Font peerFont;
106   Cursor cursor;
107   Locale locale;
108   boolean visible = true; // default (except for Window)
109   boolean enabled = true;
110   boolean valid;
111   boolean hasFocus;
112   //DropTarget dropTarget;
113   Vector popups;
114   String name;
115   boolean nameExplicitlySet;
116   Dimension minSize;
117   Dimension prefSize;
118   boolean newEventsOnly;  
119   long eventMask = AWTEvent.PAINT_EVENT_MASK;
120   PropertyChangeSupport changeSupport;
121   boolean isPacked;
122   int componentSerializedDataVersion;
123   /* AccessibleContext accessibleContext; */
124
125   /* Anything else is non-serializable, and should be declared "transient". */
126   transient Container parent;
127   transient java.awt.peer.ComponentPeer peer;
128
129   transient ComponentListener componentListener;
130   transient FocusListener focusListener;
131   transient KeyListener keyListener;
132   transient MouseListener mouseListener;
133   transient MouseMotionListener mouseMotionListener;
134   transient InputMethodListener inputMethodListener;
135   transient HierarchyListener hierarchyListener;
136   transient HierarchyBoundsListener hierarchyBoundsListener;
137
138   transient ComponentOrientation orientation = ComponentOrientation.UNKNOWN;
139
140   /**
141    * Default constructor for subclasses.
142    */
143   protected Component()
144   {
145   }
146
147   /**
148    * Returns the name of this component.
149    *
150    * @return The name of this component.
151    */
152   public String getName()
153   {
154     if (name == null && !nameExplicitlySet)
155       name = generateName();
156     return name;
157   }
158
159   /**
160    * Sets the name of this component to the specified name.
161    *
162    * @param name The new name of this component.
163    */
164   public void setName(String name)
165   {
166     nameExplicitlySet = true;
167     this.name = name;
168   }
169   
170   /** Subclasses should override this to return unique component names like 
171     * "menuitem0".
172     */
173   String generateName()
174   {
175     // Component is abstract.
176     return null;
177   }
178
179   /**
180    * Returns the parent of this component.
181    * 
182    * @return The parent of this component.
183    */
184   public Container getParent()
185   {
186     return parent;  
187   }
188
189   // Sets the peer for this component.
190   final void setPeer (ComponentPeer peer)
191   {
192     this.peer = peer;
193   }
194
195   /**
196    * Returns the native windowing system peer for this component.
197    *
198    * @return The peer for this component.
199    * @deprecated
200    */
201   // Classpath's Gtk peers rely on this.
202   public java.awt.peer.ComponentPeer getPeer()
203   {
204     return peer;
205   }
206
207   // FIXME: java.awt.dnd classes not yet implemented
208   /*
209   public void setDropTarget(DropTarget dt)
210   {
211     this.dropTarget = dt;
212   }
213   
214   public DropTarget getDropTarget()
215   {
216     return dropTarget;
217   }
218   */
219   
220   /** @since 1.3 */
221   public GraphicsConfiguration getGraphicsConfiguration()
222   {
223     return getGraphicsConfigurationImpl();
224   }
225
226   /** Implementation method that allows classes such as Canvas and
227       Window to override the graphics configuration without violating
228       the published API. */
229   GraphicsConfiguration getGraphicsConfigurationImpl()
230   {
231     if (peer != null)
232       {
233         GraphicsConfiguration config = peer.getGraphicsConfiguration();
234         if (config != null)
235           return config;
236       }
237
238     if (parent != null)
239       return parent.getGraphicsConfiguration();
240
241     return null;
242   }
243
244   /**
245    * Returns the object used for synchronization locks on this component
246    * when performing tree and layout functions.
247    *
248    * @return The synchronization lock for this component.
249    */
250   public final Object getTreeLock()
251   {
252     return treeLock;
253   }
254
255   // The sync lock object for this component.
256   final void setTreeLock(Object tree_lock)
257   {
258     this.treeLock = tree_lock;
259   }
260
261   /**
262    * Returns the toolkit in use for this component.
263    *
264    * @return The toolkit for this component.
265    */
266   public Toolkit getToolkit()
267   {
268     if (peer != null)
269       {
270         Toolkit tk = peer.getToolkit();
271         if (tk != null)
272           return tk;
273       }
274     if (parent != null)
275       return parent.getToolkit ();
276     return Toolkit.getDefaultToolkit ();
277   }
278
279   /**
280    * Tests whether or not this component is valid.  A invalid component needs
281    * to have its layout redone.
282    *
283    * @return <code>true</code> if this component is valid, <code>false</code>
284    * otherwise.
285    */
286   public boolean isValid()
287   {
288     return valid;
289   }
290   
291   /** @since 1.2 */
292   public boolean isDisplayable()
293   {
294     if (parent != null)
295       return parent.isDisplayable();
296     return false;
297   }
298
299   /**
300    * Tests whether or not this component is visible.
301    *
302    * @return <code>true</code> if the component is visible,
303    * <code>false</code> otherwise.
304    */
305   public boolean isVisible()
306   {
307     return visible;
308   }
309
310   /**
311    * Tests whether or not this component is actually being shown on
312    * the screen.  This will be true if and only if it this component is
313    * visible and its parent components are all visible.
314    *
315    * @return <code>true</code> if the component is showing on the screen,
316    * <code>false</code> otherwise.
317    */
318   public boolean isShowing()
319   {
320     if (! visible || peer == null)
321       return false;
322
323     return parent == null ? true : parent.isShowing ();
324   }
325
326   /**
327    * Tests whether or not this component is enabled.
328    *
329    * @return <code>true</code> if the component is enabled,
330    * <code>false</code> otherwise.
331    */
332   public boolean isEnabled()
333   {
334     return enabled;
335   }
336
337   /**
338    * Enables or disables this component.
339    *
340    * @param enabled <code>true</code> to enable this component, 
341    * <code>false</code> to disable it.
342    *
343    * @deprecated Deprecated in favor of <code>setEnabled()</code>.
344    */
345   public void setEnabled(boolean b)
346   {
347     this.enabled = b;
348     if (peer != null)
349       peer.setEnabled(b);
350   }
351
352   /**
353    * Enables this component.
354    *
355    * @deprecated Deprecated in favor of <code>setEnabled()</code>.
356    */
357   public void enable()
358   {
359     setEnabled(true);
360   }
361
362   /**
363    * Enables or disables this component.
364    *
365    * @param enabled <code>true</code> to enable this component, 
366    * <code>false</code> to disable it.
367    *
368    * @deprecated Deprecated in favor of <code>setEnabled()</code>.
369    */
370   public void enable(boolean b)
371   {
372     setEnabled(b);
373   }
374
375   /**
376    * Disables this component.
377    *
378    * @deprecated Deprecated in favor of <code>setEnabled()</code>.
379    */
380   public void disable()
381   {
382     setEnabled(false);
383   }
384
385   public boolean isDoubleBuffered()
386   {
387     return false;
388   }
389
390   /** @since 1.2 */
391   public void enableInputMethods(boolean enable)
392   {
393     // FIXME
394   }
395
396   /**
397    * Makes this component visible or invisible.
398    *
399    * @param visible <code>true</code> to make this component visible,
400    * </code>false</code> to make it invisible.
401    * @specnote  Inspection by subclassing shows that Sun's implementation
402    * calls show(boolean) which then calls show() or hide(). It is
403    * the show() method that is overriden in subclasses like Window.
404    * We do the same to preserve compatibility for subclasses.
405    */
406   public void setVisible(boolean b)
407   {
408     if (peer != null)
409       peer.setVisible (b);
410     this.visible = b;
411   }
412
413   /**
414    * Makes this component visible on the screen.
415    *
416    * @deprecated Deprecated in favor of <code>setVisible()</code>.
417    */
418   public void show()
419   {
420     setVisible (true);
421   }
422
423   /**
424    * Makes this component visible or invisible.
425    *
426    * @param visible <code>true</code> to make this component visible,
427    * </code>false</code> to make it invisible.
428    *
429    * @deprecated Deprecated in favor of <code>setVisible()</code>.
430    */
431   public void show(boolean b)
432   {
433     setVisible (b);
434   }
435
436   /**
437    * Hides this component so that it is no longer shown on the screen.
438    *
439    * @deprecated Deprecated in favor of <code>setVisible()</code>.
440    */
441   public void hide()
442   {
443     setVisible (false);
444   }
445
446   /**
447    * Returns this component's foreground color.
448    *
449    * @return This component's foreground color.
450    */
451   public Color getForeground()
452   {
453     if (foreground != null)
454       return foreground;
455     if (parent != null)
456       return parent.getForeground();
457     return null;
458   }
459
460   /**
461    * Sets this component's foreground color to the specified color.
462    *
463    * @param foreground_color The new foreground color.
464    */
465   public void setForeground(Color c)
466   {
467     if (peer != null)
468       peer.setForeground(c);
469     this.foreground = c;
470   }
471
472   /**
473    * Returns this component's background color.
474    *
475    * @return the background color of the component. null may be
476    * returned instead of the actual background color, if this
477    * method is called before the component is added to the
478    * component hierarchy.
479    */
480   public Color getBackground()
481   {
482     if (background != null)
483       return background;
484     if (parent != null)
485       return parent.getBackground();
486     return null;
487   }
488
489   /**
490    * Sets this component's background color to the specified color.
491    *
492    * @param background_color The new background color
493    */
494   public void setBackground(Color c)
495   {
496     if (peer != null)
497       peer.setBackground(c);
498     this.background = c;
499   }
500
501   /**
502    * Returns the font in use for this component.
503    *
504    * @return The font for this component.
505    */
506   public Font getFont()
507   {
508     if (font != null)
509       return font;
510     if (parent != null)
511       return parent.getFont();
512     return null;
513   }
514
515   /**
516    * Sets the font for this component to the specified font.
517    *
518    * @param font The new font for this component.
519    */
520   public void setFont(Font f)
521   {
522     if (peer != null)
523       peer.setFont(f);
524     this.font = f;
525   }
526
527   /**
528    * Returns the locale for this component.  If this component does not
529    * have a locale, the locale of the parent component is returned.  If the
530    * component has no parent, the system default locale is returned.
531    *
532    * @return The locale for this component.
533    */
534   public Locale getLocale() throws IllegalComponentStateException
535   {
536     if (locale != null)
537       return locale;
538     if (parent == null)
539       throw new IllegalComponentStateException
540         ("Component has no parent: Can not determine Locale");
541     return parent.getLocale();
542   }
543
544   /**
545    * Sets the locale for this component to the specified locale.
546    *
547    * @param locale The new locale for this component.
548    */
549   public void setLocale(Locale l)  
550   {
551     this.locale = l;
552
553     /* new writing/layout direction perhaps, or make more/less
554        room for localized text labels */
555     invalidate();
556   }
557
558   /**
559    * Returns the color model of the device this componet is displayed on.
560    *
561    * @return This object's color model.
562    */
563   public ColorModel getColorModel()
564   {
565     GraphicsConfiguration config = getGraphicsConfiguration();
566
567     if (config != null)
568       return config.getColorModel();
569
570     return getToolkit().getColorModel();    
571   }
572
573   /**
574    * Returns the location of this component's top left corner relative to
575    * its parent component.
576    *
577    * @return The location of this component.
578    */
579   public Point getLocation()
580   {
581     return new Point(x, y);
582   }
583
584   /**
585    * Returns the location of this component's top left corner in screen
586    * coordinates.
587    *
588    * @return The location of this component in screen coordinates.
589    */
590   public Point getLocationOnScreen()
591   {
592     if (! isShowing ())
593       throw new IllegalComponentStateException ("component not showing");
594
595     // We know peer != null here.
596     return peer.getLocationOnScreen ();
597   }
598
599   /**
600    * Returns the location of this component's top left corner relative to
601    * its parent component.
602    *
603    * @return The location of this component.
604    *
605    * @deprecated This method is deprecated in favor of 
606    * <code>getLocation()</code>.
607    */
608   public Point location()
609   {
610     return getLocation();
611   }
612
613   /**
614    * Moves this component to the specified location.  The coordinates are
615    * the new upper left corner of this component.
616    *
617    * @param x The new X coordinate of this component.
618    * @param y The new Y coordinate of this component.
619    */
620   public void setLocation (int x, int y)
621   {
622     if ((this.x == x) && (this.y == y))
623       return;
624
625     invalidate();
626
627     this.x = x;
628     this.y = y;
629     if (peer != null)
630       peer.setBounds(x, y, width, height);
631   }
632
633   /**
634    * Moves this component to the specified location.  The coordinates are
635    * the new upper left corner of this component.
636    *
637    * @param x The new X coordinate of this component.
638    * @param y The new Y coordinate of this component.
639    *
640    * @deprecated Deprecated in favor for <code>setLocation</code>.
641    */
642   public void move(int x, int y)
643   {
644     setLocation(x,y);
645   }
646
647   /**
648    * Moves this component to the specified location.  The coordinates are
649    * the new upper left corner of this component.
650    *
651    * @param p New coordinates for this component.
652    */
653   public void setLocation(Point p)
654   {
655     setLocation(p.x, p.y);
656   }
657
658   /**
659    * Returns the size of this object.
660    *
661    * @return The size of this object.
662    */
663   public Dimension getSize()
664   {
665     return new Dimension(width, height);
666   }
667
668   /**
669    * Returns the size of this object.
670    *
671    * @return The size of this object.
672    *
673    * @deprecated This method is deprecated in favor of <code>getSize</code>.
674    */
675   public Dimension size()
676   {
677     return getSize();
678   }
679
680   /**
681    * Sets the size of this component to the specified width and height.
682    * 
683    * @param width The new width of this component.
684    * @param height The new height of this component.
685    */
686   public void setSize(int width, int height)
687   {
688     if ((this.width == width) && (this.height == height))
689       return;
690
691     invalidate();
692
693     this.width = width;
694     this.height = height;
695     if (peer != null)
696       peer.setBounds(x, y, width, height);
697   }
698
699   /**
700    * Sets the size of this component to the specified value.
701    * 
702    * @param width The new width of the component.
703    * @param height The new height of the component.
704    *
705    * @deprecated This method is deprecated in favor of <code>setSize</code>.
706    */
707   public void resize(int width, int height)
708   {
709     setSize(width, height);
710   }
711
712   /**
713    * Sets the size of this component to the specified value.
714    * 
715    * @param dim The new size of this component.
716    */
717   public void setSize(Dimension d)
718   {
719     setSize(d.width, d.height);
720   }
721
722   /**
723    * Sets the size of this component to the specified value.
724    * 
725    * @param dim The new size of this component.
726    *
727    * @deprecated This method is deprecated in favor of <code>setSize</code>.
728    */
729   public void resize(Dimension d)
730   {
731     setSize(d.width, d.height);
732   }
733
734   /**
735    * Returns a bounding rectangle for this component.  Note that the
736    * returned rectange is relative to this component's parent, not to
737    * the screen.
738    *
739    * @return The bounding rectangle for this component.
740    */
741   public Rectangle getBounds()
742   {
743     return new Rectangle (x, y, width, height);
744   }
745
746   /**
747    * Returns a bounding rectangle for this component.  Note that the
748    * returned rectange is relative to this component's parent, not to
749    * the screen.
750    *
751    * @return The bounding rectangle for this component.
752    *
753    * @deprecated Deprecated in favor of <code>getBounds()</code>.
754    */
755   public Rectangle bounds()
756   {
757     return getBounds();
758   }
759
760   /**
761    * Sets the bounding rectangle for this component to the specified
762    * values.  Note that these coordinates are relative to the parent,
763    * not to the screen.
764    *
765    * @param x The X coordinate of the upper left corner of the rectangle.
766    * @param y The Y coordinate of the upper left corner of the rectangle.
767    * @param width The width of the rectangle.
768    * @param height The height of the rectangle.
769    */
770   public void setBounds(int x, int y, int w, int h)
771   {
772     if (this.x == x
773         && this.y == y
774         && this.width == w
775         && this.height == h)
776       return;
777
778     invalidate();
779
780     this.x = x;
781     this.y = y;
782     this.width = w;
783     this.height = h;
784
785     if (peer != null)
786       peer.setBounds(x, y, w, h);
787   }
788
789   /**
790    * Sets the bounding rectangle for this component to the specified
791    * values.  Note that these coordinates are relative to the parent,
792    * not to the screen.
793    *
794    * @param x The X coordinate of the upper left corner of the rectangle.
795    * @param y The Y coordinate of the upper left corner of the rectangle.
796    * @param width The width of the rectangle.
797    * @param height The height of the rectangle.
798    *
799    * @deprecated This method is deprecated in favor of
800    * <code>setBounds(int, int, int, int)</code>.
801    */
802   public void reshape(int x, int y, int width, int height)
803   {
804     setBounds(x, y, width, height);
805   }
806
807   /**
808    * Sets the bounding rectangle for this component to the specified
809    * rectangle.  Note that these coordinates are relative to the parent,
810    * not to the screen.
811    *
812    * @param bounding_rectangle The new bounding rectangle.
813    */
814   public void setBounds(Rectangle r)
815   { 
816     setBounds(r.x, r.y, r.width, r.height);
817   }
818   
819   /** @since 1.2 */
820   public int getX()
821   {
822     return x;
823   }
824   
825   /** @since 1.2 */
826   public int getY()
827   {
828     return y;
829   }
830   
831   /** @since 1.2 */
832   public int getWidth()
833   {
834     return width;
835   }
836   
837   /** @since 1.2 */
838   public int getHeight()
839   {
840     return height;
841   }
842   
843   public Rectangle getBounds(Rectangle r)
844   {
845     r.x = this.x;
846     r.y = this.y;
847     r.width = this.width;
848     r.height = this.height;
849     return r;
850   }
851   
852   public Dimension getSize(Dimension d)
853   {
854     d.width = this.width;
855     d.height = this.height;
856     return d;
857   }
858   
859   public Point getLocation(Point p)
860   {
861     p.x = x;
862     p.y = y;
863     return p;
864   }
865   
866   /** @since 1.2 */
867   public boolean isOpaque()
868   {
869     return !isLightweight();
870   }
871   
872   /** 
873    * Return whether the component is lightweight.
874    *
875    * @return true if component has a peer and and the peer is lightweight.
876    *
877    * @since 1.2
878    */  
879   public boolean isLightweight()
880   {
881     return (peer != null) && (peer instanceof LightweightPeer);
882   }
883
884   /**
885    * Returns the component's preferred size.
886    *
887    * @return The component's preferred size.
888    */
889   public Dimension getPreferredSize()
890   {
891     if (peer == null)
892       return new Dimension(width, height);
893     else
894       return peer.getPreferredSize();
895   }
896
897   /**
898    * Returns the component's preferred size.
899    *
900    * @return The component's preferred size.
901    *
902    * @deprecated Deprecated in favor of <code>getPreferredSize()</code>.
903    */
904   public Dimension preferredSize()
905   {
906     return getPreferredSize();
907   }
908
909   /**
910    * Returns the component's minimum size.
911    *
912    * @return The component's minimum size.
913    */
914   public Dimension getMinimumSize()
915   {
916     if (peer == null)
917       return new Dimension(width, height);
918     else
919       return peer.getMinimumSize();
920   }
921
922   /**
923    * Returns the component's minimum size.
924    *
925    * @return The component's minimum size.
926    *
927    * @deprecated Deprecated in favor of <code>getMinimumSize()</code>
928    */
929   public Dimension minimumSize()
930   {
931     return getMinimumSize();
932   }
933
934   /**
935    * Returns the component's maximum size.
936    *
937    * @return The component's maximum size.
938    */
939   public Dimension getMaximumSize()
940   {
941     return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
942   }
943
944   /**
945    * Returns the preferred horizontal alignment of this component.  The
946    * value returned will be one of the constants defined in this class.
947    *
948    * @return The preferred horizontal alignment of this component.
949    */
950   public float getAlignmentX()
951   {
952     return CENTER_ALIGNMENT;
953   }
954
955   /**
956    * Returns the preferred vertical alignment of this component.  The
957    * value returned will be one of the constants defined in this class.
958    *
959    * @return The preferred vertical alignment of this component.
960    */
961   public float getAlignmentY()
962   {
963     return CENTER_ALIGNMENT;
964   }
965
966   /**
967    * Calls the layout manager to re-layout the component.  This is called
968    * during validation of a container in most cases.
969    */
970   public void doLayout()
971   {
972     // nothing to do unless we're a container
973   }
974
975   /**
976    * Calls the layout manager to re-layout the component.  This is called
977    * during validation of a container in most cases.
978    *
979    * @deprecated This method is deprecated in favor of <code>doLayout()</code>.
980    */
981   public void layout()
982   {
983     doLayout();
984   }
985
986   /**
987    * Called to ensure that the layout for this component is valid.
988    */
989   public void validate()
990   {
991     valid = true;
992   }
993
994   /**
995    * Invalidates this component and all of its parent components.  This will
996    * cause them to have their layout redone.
997    */
998   public void invalidate()
999   {
1000     valid = false;
1001
1002     if ((parent != null) && parent.valid)
1003       parent.invalidate ();
1004   }
1005
1006   /**
1007    * Returns a graphics object for this component.  Returns <code>null</code>
1008    * if this component is not currently displayed on the screen.
1009    *
1010    * @return A graphics object for this component.
1011    */
1012   public Graphics getGraphics()
1013   {
1014     if (peer != null)
1015       {
1016         Graphics gfx = peer.getGraphics();
1017         if (gfx != null)
1018           return gfx;
1019       
1020         // create graphics for lightweight:
1021         Container parent = getParent();
1022         if (parent != null)
1023           {
1024             gfx = parent.getGraphics();
1025             Rectangle bounds = getBounds();
1026             gfx.setClip(bounds);
1027             gfx.translate(bounds.x, bounds.y);
1028             return gfx;
1029           }
1030       }
1031     return null;
1032   }
1033
1034   /**
1035    * Returns the font metrics for the specified font in this component.
1036    *
1037    * @param font The font to retrieve metrics for.
1038    *
1039    * @return The font metrics for the specified font.
1040    */
1041   public FontMetrics getFontMetrics(Font font)
1042   {
1043     if (peer == null)
1044       return getToolkit().getFontMetrics(font);
1045     return peer.getFontMetrics (font);
1046   }
1047
1048   /**
1049    * Sets the cursor for this component to the specified cursor.
1050    *
1051    * @param cursor The new cursor for this component.
1052    */
1053   public void setCursor(Cursor cursor)
1054   {
1055     this.cursor = cursor;
1056     if (peer != null)
1057       peer.setCursor (cursor);
1058   }
1059
1060   /**
1061    * Returns the cursor for this component.
1062    *
1063    * @return The cursor for this component.
1064    */
1065   public Cursor getCursor()
1066   {
1067     return this.cursor;
1068   }
1069
1070   /**
1071    * Paints this component on the screen.  The clipping region in the
1072    * graphics context will indicate the region that requires painting.
1073    *
1074    * @param graphics The graphics context for this paint job.
1075    */
1076   public void paint(Graphics g)
1077   {
1078   }
1079
1080   /**
1081    * Updates this component.  This method fills the component
1082    * with the background color, then sets the foreground color of the
1083    * specified graphics context to the foreground color of this component
1084    * and calls the <code>paint()</code> method.
1085    * // FIXME: What are the coords relative to?
1086    *
1087    * @param graphics The graphics context for this update.
1088    */
1089   public void update(Graphics g)
1090   {
1091     paint(g);
1092   }
1093
1094   /**
1095    * Paints this entire component, including any sub-components.
1096    *
1097    * @param graphics The graphics context for this paint job.
1098    */
1099   public void paintAll(Graphics g)
1100   {    
1101     if (!visible)
1102       return;
1103         
1104     if (peer != null)
1105       peer.paint(g);
1106     paint(g);
1107   }
1108
1109   /**
1110    * Repaint this entire component.  The <code>update()</code> method
1111    * on this component will be called as soon as possible.
1112    * // FIXME: What are the coords relative to?
1113    */
1114   public void repaint()
1115   {
1116     repaint(0, 0, 0, getWidth(), getHeight());
1117   }
1118
1119   /**
1120    * Repaint this entire component.  The <code>update()</code> method
1121    * on this component will be called in approximate the specified number
1122    * of milliseconds.
1123    * // FIXME: What are the coords relative to?
1124    *
1125    * @param tm The number of milliseconds before this component should
1126    * be repainted.
1127    */
1128   public void repaint(long tm)
1129   {
1130     repaint(tm, 0, 0, getWidth(), getHeight());
1131   }
1132
1133   /**
1134    * Repaints the specified rectangular region within this component.
1135    * This <code>update</code> method on this component will be called as
1136    * soon as possible.
1137    * // FIXME: What are the coords relative to?
1138    *
1139    * @param x The X coordinate of the upper left of the region to repaint
1140    * @param y The Y coordinate of the upper left of the region to repaint
1141    * @param width The width of the region to repaint.
1142    * @param height The height of the region to repaint.
1143    */
1144   public void repaint(int x, int y, int width, int height)
1145   {
1146     repaint(0, x, y, width, height);
1147   }
1148
1149   /**
1150    * Repaints the specified rectangular region within this component.
1151    * This <code>update</code> method on this component will be called in
1152    * approximately the specified number of milliseconds.
1153    * // FIXME: What are the coords relative to?
1154    *
1155    * @param tm The number of milliseconds before this component should
1156    * be repainted.
1157    * @param x The X coordinate of the upper left of the region to repaint
1158    * @param y The Y coordinate of the upper left of the region to repaint
1159    * @param width The width of the region to repaint.
1160    * @param height The height of the region to repaint.
1161    */
1162   public void repaint(long tm, int x, int y, int width, int height)
1163   {    
1164     // Handle lightweight repainting by forwarding to native parent
1165     if (isLightweight() && (parent != null))
1166       {
1167         if (parent != null)
1168           parent.repaint(tm, x+getX(), y+getY(), width, height);
1169         return;
1170       }
1171
1172     if (peer != null)
1173       peer.repaint(tm, x, y, width, height);
1174   }
1175
1176   /**
1177    * Prints this component.  This method is
1178    * provided so that printing can be done in a different manner from
1179    * painting.  However, the implementation in this class simply calls
1180    * the <code>paint()</code> method.
1181    *
1182    * @param graphics The graphics context of the print device.
1183    */
1184   public void print(Graphics g)
1185   {
1186     paint(g);
1187   }
1188
1189   /**
1190    * Prints this component, including all sub-components.  This method is
1191    * provided so that printing can be done in a different manner from
1192    * painting.  However, the implementation in this class simply calls
1193    * the <code>paintAll()</code> method.
1194    *
1195    * @param graphics The graphics context of the print device.
1196    */
1197   public void printAll(Graphics g)
1198   {
1199     paintAll(g);
1200   }
1201
1202   /**
1203    * Called when an image has changed so that this component is
1204    * repainted.
1205    *
1206    * @param image The image that has been updated.
1207    * @param flags Flags as specified in <code>ImageObserver</code>.
1208    * @param x The X coordinate 
1209    * @param y The Y coordinate
1210    * @param width The width
1211    * @param height The height
1212    *
1213    * @return <code>true</code> if the image has been fully loaded,
1214    * <code>false</code> otherwise.
1215    */
1216   public boolean imageUpdate (Image img, int infoflags, int x, int y,
1217                               int w, int h)
1218   {
1219     // FIXME
1220     return false;
1221   }
1222
1223   /**
1224    * Creates an image from the specified producer.
1225    *
1226    * @param producer The image procedure to create the image from.
1227    *
1228    * @return The resulting image.
1229    */
1230   public Image createImage(ImageProducer producer)
1231   {
1232     return peer.createImage(producer);
1233   }
1234
1235   /**
1236    * Creates an image with the specified width and height for use in
1237    * double buffering.
1238    *
1239    * @param width The width of the image.
1240    * @param height The height of the image.
1241    *
1242    * @return The requested image.
1243    */
1244   public Image createImage(int width, int height)
1245   {
1246     return getGraphicsConfiguration().createCompatibleImage(width, height);
1247   }
1248
1249   /**
1250    * Prepares the specified image for rendering on this component.
1251    *
1252    * @param image The image to prepare for rendering.
1253    * @param observer The image observer to notify of the status of the
1254    * image preparation.
1255    *
1256    * @return <code>true</code> if the image is already fully prepared
1257    * for rendering, <code>false</code> otherwise.
1258    */
1259   public boolean prepareImage(Image image, ImageObserver observer)
1260   {
1261     return prepareImage(image, image.getWidth(observer), 
1262                         image.getHeight(observer), observer);
1263   }
1264
1265   /**
1266    * Prepares the specified image for rendering on this component at the
1267    * specified scaled width and height
1268    *
1269    * @param image The image to prepare for rendering.
1270    * @param width The scaled width of the image.
1271    * @param height The scaled height of the image.
1272    * @param observer The image observer to notify of the status of the
1273    * image preparation.
1274    *
1275    * @return <code>true</code> if the image is already fully prepared
1276    * for rendering, <code>false</code> otherwise.
1277    */
1278   public boolean prepareImage(Image image, int width, int height,
1279                               ImageObserver observer)
1280   {
1281     return peer.prepareImage(image, width, height, observer);
1282   }
1283
1284   /**
1285    * Returns the status of the loading of the specified image. The value
1286    * returned will be those flags defined in <code>ImageObserver</code>.
1287    *
1288    * @param image The image to check on.
1289    * @param observer The observer to be notified as the image loading
1290    * progresses.
1291    *
1292    * @return The image observer flags indicating the status of the load.
1293    */
1294   public int checkImage(Image image, ImageObserver observer)
1295   {
1296     return checkImage(image, image.getWidth(observer), 
1297                       image.getHeight(observer), observer);
1298   }
1299
1300   /**
1301    * Returns the status of the loading of the specified image. The value
1302    * returned will be those flags defined in <code>ImageObserver</code>.
1303    *
1304    * @param image The image to check on.
1305    * @param width The scaled image width.
1306    * @param height The scaled image height.
1307    * @param observer The observer to be notified as the image loading
1308    * progresses.
1309    *
1310    * @return The image observer flags indicating the status of the load.
1311    */
1312   public int checkImage (Image image, int width, int height,
1313                          ImageObserver observer)
1314   {
1315     if (peer != null)
1316       return peer.checkImage (image, width, height, observer);
1317     return getToolkit ().checkImage (image, width, height, observer);
1318   }
1319
1320   /**
1321    * Tests whether or not the specified point is contained within this
1322    * component.  Coordinates are relative to this component.
1323    *
1324    * @param x The X coordinate of the point to test.
1325    * @param y The Y coordinate of the point to test.
1326    *
1327    * @return <code>true</code> if the point is within this component,
1328    * <code>false</code> otherwise.
1329    */
1330   public boolean contains (int x, int y)
1331   {
1332     return (x >= 0) && (y >= 0) && (x < width) && (y < height);
1333   }
1334
1335   /**
1336    * Tests whether or not the specified point is contained within this
1337    * component.  Coordinates are relative to this component.
1338    *
1339    * @param x The X coordinate of the point to test.
1340    * @param y The Y coordinate of the point to test.
1341    *
1342    * @return <code>true</code> if the point is within this component,
1343    * <code>false</code> otherwise.
1344    *
1345    * @deprecated Deprecated in favor of <code>contains(int, int)</code>.
1346    */
1347   public boolean inside(int x, int y)
1348   {
1349     return contains(x,y);
1350   }
1351
1352   /**
1353    * Tests whether or not the specified point is contained within this
1354    * component.  Coordinates are relative to this component.
1355    *
1356    * @param point The point to test.
1357    *
1358    * @return <code>true</code> if the point is within this component,
1359    * <code>false</code> otherwise.
1360    */
1361   public boolean contains(Point p)
1362   {
1363     return contains(p.x, p.y);
1364   }
1365
1366   /**
1367    * Returns the component occupying the position (x,y).  This will either
1368    * be this component, an immediate child component, or <code>null</code>
1369    * if neither of the first two occupies the specified location.
1370    *
1371    * @param x The X coordinate to search for components at.
1372    * @param y The Y coordinate to search for components at.
1373    *
1374    * @return The component at the specified location, for <code>null</code>
1375    * if there is none.
1376    */
1377   public Component getComponentAt(int x, int y)
1378   {
1379     if (contains(x,y))
1380       return this;
1381     return null;
1382   }
1383
1384   /**
1385    * Returns the component occupying the position (x,y).  This will either
1386    * be this component, an immediate child component, or <code>null</code>
1387    * if neither of the first two occupies the specified location.
1388    *
1389    * @param x The X coordinate to search for components at.
1390    * @param y The Y coordinate to search for components at.
1391    *
1392    * @return The component at the specified location, for <code>null</code>
1393    * if there is none.
1394    *
1395    * @deprecated The method is deprecated in favor of 
1396    * <code>getComponentAt()</code>.
1397    */
1398   public Component locate(int x, int y)
1399   {
1400     return getComponentAt(x, y);
1401   }
1402
1403   /**
1404    * Returns the component occupying the specified point  This will either
1405    * be this component, an immediate child component, or <code>null</code>
1406    * if neither of the first two occupies the specified location.
1407    *
1408    * @param point The point to search for components at.
1409    *
1410    * @return The component at the specified location, for <code>null</code>
1411    * if there is none.
1412    */
1413   public Component getComponentAt(Point p)
1414   {
1415     return getComponentAt(p.x, p.y);
1416   }
1417
1418   /**
1419    * AWT 1.0 event dispatcher.
1420    *
1421    * @deprecated Deprecated in favor of <code>dispatchEvent()</code>.
1422    */
1423   public void deliverEvent(Event e)
1424   {
1425   }
1426
1427   /** Forward AWT events to processEvent() if:
1428     *     - Events have been enabled for this type of event via enableEvents(),
1429     *   OR:
1430     *    - There is at least one registered listener for this type of event
1431     * 
1432     * @param event The event to dispatch
1433     *
1434     * @specnote This method is final, but we need to be able to 
1435     *           override it in order to handle other event types in our 
1436     *           subclasses. The solution is to define a second, non-final
1437     *           method - dispatchEventImpl() - to actually do the work. 
1438     *           Investigations with Thread.dumpStack() on the dispatch thread 
1439     *           in JDK 1.3 show Sun's implementation is doing the same 
1440     *           thing.
1441     */
1442   public final void dispatchEvent(AWTEvent e)
1443   {
1444     dispatchEventImpl(e);
1445
1446     /* Give the peer a chance to handle the event. */
1447     if (peer != null)
1448       peer.handleEvent(e);
1449   }
1450
1451   void dispatchEventImpl(AWTEvent e)
1452   {
1453     // Make use of event id's in order to avoid multiple instanceof tests.
1454     if (e.id <= ComponentEvent.COMPONENT_LAST 
1455         && e.id >= ComponentEvent.COMPONENT_FIRST
1456         && (componentListener != null 
1457             || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0))
1458       processEvent(e);
1459     else if (e.id <= KeyEvent.KEY_LAST
1460              && e.id >= KeyEvent.KEY_FIRST
1461              && (keyListener != null
1462                  || (eventMask & AWTEvent.KEY_EVENT_MASK) != 0))
1463       processEvent(e);
1464     else if (e.id <= MouseEvent.MOUSE_LAST
1465              && e.id >= MouseEvent.MOUSE_FIRST
1466              && (mouseListener != null
1467                  || mouseMotionListener != null
1468                  || (eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0))
1469       processEvent(e);
1470     else if (e.id <= FocusEvent.FOCUS_LAST
1471              && e.id >= FocusEvent.FOCUS_FIRST
1472              && (focusListener != null
1473                  || (eventMask & AWTEvent.FOCUS_EVENT_MASK) != 0))
1474       processEvent(e);
1475     else if (e.id <= InputMethodEvent.INPUT_METHOD_LAST
1476              && e.id >= InputMethodEvent.INPUT_METHOD_FIRST
1477              && (inputMethodListener != null
1478                  || (eventMask & AWTEvent.INPUT_METHOD_EVENT_MASK) != 0))
1479       processEvent(e);
1480     else if (e.id <= HierarchyEvent.HIERARCHY_LAST
1481              && e.id >= HierarchyEvent.HIERARCHY_FIRST
1482              && (hierarchyListener != null
1483                  || hierarchyBoundsListener != null
1484                  || (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) != 0))
1485       processEvent(e);
1486     else if (e.id <= PaintEvent.PAINT_LAST
1487              && e.id >= PaintEvent.PAINT_FIRST
1488              && (eventMask & AWTEvent.PAINT_EVENT_MASK) != 0)      
1489       processEvent(e);
1490   }
1491   
1492   /**
1493    * AWT 1.0 event dispatcher.
1494    *
1495    * @deprecated Deprecated in favor of <code>dispatchEvent()</code>.
1496    */
1497   public boolean postEvent(Event e)
1498   {
1499     return false;
1500   }
1501
1502   /**
1503    * Adds the specified listener to this component.
1504    *
1505    * @param listener The new listener to add.
1506    */
1507   public synchronized void addComponentListener(ComponentListener l)
1508   {
1509     componentListener = AWTEventMulticaster.add(componentListener, l);
1510     if (componentListener != null)
1511       enableEvents(AWTEvent.COMPONENT_EVENT_MASK);
1512   }
1513
1514   /**
1515    * Removes the specified listener from the component.
1516    *
1517    * @param listener The listener to remove.
1518    */
1519   public synchronized void removeComponentListener(ComponentListener l)
1520   {
1521     componentListener = AWTEventMulticaster.remove(componentListener, l);
1522   }
1523
1524   /**
1525    * Adds the specified listener to this component.
1526    *
1527    * @param listener The new listener to add.
1528    */
1529   public synchronized void addFocusListener(FocusListener l)
1530   {
1531     focusListener = AWTEventMulticaster.add(focusListener, l);
1532     if (focusListener != null)
1533       enableEvents(AWTEvent.FOCUS_EVENT_MASK);    
1534   }
1535
1536   /**
1537    * Removes the specified listener from the component.
1538    *
1539    * @param listener The listener to remove.
1540    */
1541   public synchronized void removeFocusListener(FocusListener l)
1542   {
1543     focusListener = AWTEventMulticaster.remove(focusListener, l);
1544   }
1545   
1546   /** @since 1.3 */
1547   public synchronized void addHierarchyListener(HierarchyListener l)
1548   {
1549     hierarchyListener = AWTEventMulticaster.add(hierarchyListener, l);
1550     if (hierarchyListener != null)
1551       enableEvents(AWTEvent.HIERARCHY_EVENT_MASK);    
1552   }
1553   
1554   /** @since 1.3 */
1555   public synchronized void removeHierarchyListener(HierarchyListener l)
1556   {
1557     hierarchyListener = AWTEventMulticaster.remove(hierarchyListener, l);
1558   }
1559
1560   /** @since 1.3 */
1561   public synchronized void addHierarchyBoundsListener(HierarchyBoundsListener l)
1562   {
1563     hierarchyBoundsListener = 
1564       AWTEventMulticaster.add(hierarchyBoundsListener, l);
1565     if (hierarchyBoundsListener != null)
1566       enableEvents(AWTEvent.HIERARCHY_EVENT_MASK);    
1567   }
1568
1569   /** @since 1.3 */
1570   public synchronized void 
1571     removeHierarchyBoundsListener(HierarchyBoundsListener l)
1572   {
1573     hierarchyBoundsListener = 
1574       AWTEventMulticaster.remove(hierarchyBoundsListener, l);
1575   }
1576
1577   /**
1578    * Adds the specified listener to this component.
1579    *
1580    * @param listener The new listener to add.
1581    */
1582   public synchronized void addKeyListener(KeyListener l)
1583   {
1584     keyListener = AWTEventMulticaster.add(keyListener, l);
1585     if (keyListener != null)
1586       enableEvents(AWTEvent.KEY_EVENT_MASK);    
1587   }
1588
1589   /**
1590    * Removes the specified listener from the component.
1591    *
1592    * @param listener The listener to remove.
1593    */
1594   public synchronized void removeKeyListener(KeyListener l)
1595   {
1596     keyListener = AWTEventMulticaster.remove(keyListener, l);
1597   }
1598
1599   /**
1600    * Adds the specified listener to this component.
1601    *
1602    * @param listener The new listener to add.
1603    */
1604   public synchronized void addMouseListener(MouseListener l)
1605   {
1606     mouseListener = AWTEventMulticaster.add(mouseListener, l);
1607     if (mouseListener != null)
1608       enableEvents(AWTEvent.MOUSE_EVENT_MASK);    
1609   }
1610
1611   /**
1612    * Removes the specified listener from the component.
1613    *
1614    * @param listener The listener to remove.
1615    */
1616   public synchronized void removeMouseListener(MouseListener l)
1617   {
1618     mouseListener = AWTEventMulticaster.remove(mouseListener, l);    
1619   }
1620
1621   /**
1622    * Adds the specified listener to this component.
1623    *
1624    * @param listener The new listener to add.
1625    */
1626   public synchronized void addMouseMotionListener(MouseMotionListener l)
1627   {
1628     mouseMotionListener = AWTEventMulticaster.add(mouseMotionListener, l);
1629     if (mouseMotionListener != null)
1630       enableEvents(AWTEvent.MOUSE_EVENT_MASK);    
1631   }
1632
1633   /**
1634    * Removes the specified listener from the component.
1635    *
1636    * @param listener The listener to remove.
1637    */
1638   public synchronized void removeMouseMotionListener(MouseMotionListener l)
1639   {
1640     mouseMotionListener = AWTEventMulticaster.remove(mouseMotionListener, l);
1641   }
1642
1643   /** @since 1.2 */
1644   public synchronized void addInputMethodListener(InputMethodListener l)
1645   {
1646     inputMethodListener = AWTEventMulticaster.add(inputMethodListener, l);
1647     if (inputMethodListener != null)
1648       enableEvents(AWTEvent.INPUT_METHOD_EVENT_MASK);    
1649   }
1650
1651   /** @since 1.2 */
1652   public synchronized void removeInputMethodListener(InputMethodListener l)
1653   {
1654     inputMethodListener = AWTEventMulticaster.remove(inputMethodListener, l);
1655   }
1656
1657   /** Returns all registered EventListers of the given listenerType. 
1658     * listenerType must be a subclass of EventListener, or a 
1659     * ClassClassException is thrown.
1660     * @since 1.3 
1661     */
1662   public EventListener[] getListeners(Class listenerType)
1663   {
1664     if (listenerType == ComponentListener.class)
1665       return getListenersImpl(listenerType, componentListener);
1666     else if (listenerType == FocusListener.class)
1667       return getListenersImpl(listenerType, focusListener);
1668     else if (listenerType == KeyListener.class)
1669       return getListenersImpl(listenerType, keyListener);
1670     else if (listenerType == MouseListener.class)
1671       return getListenersImpl(listenerType, mouseListener);
1672     else if (listenerType == MouseMotionListener.class)
1673       return getListenersImpl(listenerType, mouseMotionListener);
1674     else if (listenerType == InputMethodListener.class)
1675       return getListenersImpl(listenerType, inputMethodListener);
1676     else if (listenerType == HierarchyListener.class)
1677       return getListenersImpl(listenerType, hierarchyListener);
1678     else if (listenerType == HierarchyBoundsListener.class)
1679       return getListenersImpl(listenerType, hierarchyBoundsListener);
1680     else
1681       return getListenersImpl(listenerType, null);
1682   }
1683   
1684   static EventListener[] getListenersImpl(Class listenerType, EventListener el)
1685   {
1686     if (! EventListener.class.isAssignableFrom(listenerType))
1687       throw new ClassCastException();
1688     
1689     Vector v = new Vector();
1690     if (el != null)
1691       getListenerList (el, v);    
1692     EventListener[] el_a = (EventListener[]) Array.newInstance(listenerType, 
1693                                                                v.size());
1694     v.copyInto(el_a);
1695     return el_a;
1696   }
1697
1698   static void getListenerList(EventListener el, Vector v)
1699   {
1700     if (el instanceof AWTEventMulticaster)
1701       {
1702         AWTEventMulticaster mc = (AWTEventMulticaster) el;
1703         getListenerList(mc.a, v);
1704         getListenerList(mc.b, v);
1705       }
1706     else
1707       v.addElement(el);      
1708   }
1709
1710   // The input method framework is currently unimplemented.  
1711   // /** @since 1.2 */
1712   //
1713   //public InputMethodRequests getInputMethodRequests()
1714   //
1715   // /** @since 1.2 */
1716   //
1717   // public InputContext getInputContext()
1718
1719   /**
1720    * Enables the specified events.  The events to enable are specified
1721    * by OR-ing together the desired masks from <code>AWTEvent</code>.
1722    * <p>
1723    * Events are enabled by default when a listener is attached to the
1724    * component for that event type.  This method can be used by subclasses
1725    * to ensure the delivery of a specified event regardless of whether
1726    * or not a listener is attached.
1727    *
1728    * @param enable_events The desired events to enable.
1729    */
1730   protected final void enableEvents(long eventsToEnable)
1731   {
1732     eventMask |= eventsToEnable;
1733     // TODO: Unlike Sun's implementation, I think we should try and 
1734     // enable/disable events at the peer (gtk/X) level. This will avoid 
1735     // clogging the event pipeline with useless mousemove events that 
1736     // we arn't interested in, etc. This will involve extending the peer 
1737     // interface, but thats okay because the peer interfaces have been
1738     // deprecated for a long time, and no longer feature in the 
1739     // API specification at all.
1740
1741     if (isLightweight() && (parent != null))
1742       parent.enableEvents(eventsToEnable);
1743     else if (peer != null)
1744       peer.setEventMask (eventMask);
1745   }
1746
1747   /**
1748    * Disables the specified events.  The events to disable are specified
1749    * by OR-ing together the desired masks from <code>AWTEvent</code>.
1750    *
1751    * @param disable_events The desired events to disable.
1752    */
1753   protected final void disableEvents(long eventsToDisable)
1754   {
1755     eventMask &= ~eventsToDisable;
1756     // forward new event mask to peer?
1757   }
1758
1759   /** coalesceEvents is called by the EventQueue if two events with the same 
1760     * event id are queued. Returns a new combined event, or null if no 
1761     * combining is done. 
1762     */
1763   protected AWTEvent coalesceEvents(AWTEvent existingEvent, AWTEvent newEvent)
1764   {
1765     switch (existingEvent.id)
1766       {
1767       case MouseEvent.MOUSE_MOVED:
1768       case MouseEvent.MOUSE_DRAGGED:
1769         // Just drop the old (intermediate) event and return the new one.
1770         return newEvent;
1771       case PaintEvent.PAINT:
1772       case PaintEvent.UPDATE:
1773         return coalescePaintEvents((PaintEvent) existingEvent,
1774                                    (PaintEvent) newEvent);
1775       }
1776     return null;
1777   }
1778   
1779   /**
1780    * Coalesce paint events. Current heuristic is: Merge if the union of
1781    * areas is less than twice that of the sum of the areas. The X server
1782    * tend to create a lot of paint events that are adjacent but not
1783    * overlapping.
1784    *
1785    * <pre>
1786    * +------+
1787    * |      +-----+  ...will be merged
1788    * |      |     |
1789    * |      |     |
1790    * +------+     |
1791    *        +-----+
1792    * 
1793    * +---------------+--+
1794    * |               |  |  ...will not be merged
1795    * +---------------+  |
1796    *                 |  |
1797    *                 |  |
1798    *                 |  |
1799    *                 |  |
1800    *                 |  |
1801    *                 +--+
1802    * </pre>
1803    */
1804   private PaintEvent coalescePaintEvents(PaintEvent queuedEvent,
1805                                          PaintEvent newEvent)
1806   {
1807     Rectangle r1 = queuedEvent.getUpdateRect();
1808     Rectangle r2 = newEvent.getUpdateRect();
1809     Rectangle union = r1.union(r2);
1810     
1811     int r1a = r1.width * r1.height;
1812     int r2a = r2.width * r2.height;
1813     int ua  = union.width * union.height;
1814     
1815     if (ua > (r1a+r2a)*2)
1816       return null;
1817     /* The 2 factor should maybe be reconsidered. Perhaps 3/2
1818        would be better? */
1819
1820     newEvent.setUpdateRect(union);
1821     return newEvent;
1822   }
1823
1824   /**
1825    * Processes the specified event.  In this class, this method simply
1826    * calls one of the more specific event handlers.
1827    * 
1828    * @param event The event to process.
1829    */
1830   protected void processEvent(AWTEvent e)
1831   {
1832
1833     /* Note: the order of these if statements are
1834        important. Subclasses must be checked first. Eg. MouseEvent
1835        must be checked before ComponentEvent, since a MouseEvent
1836        object is also an instance of a ComponentEvent. */
1837
1838     if (e instanceof FocusEvent)
1839       processFocusEvent((FocusEvent) e);
1840     else if (e instanceof PaintEvent)
1841       processPaintEvent((PaintEvent) e);
1842     else if (e instanceof MouseEvent)
1843       {
1844         if (e.id == MouseEvent.MOUSE_MOVED 
1845             || e.id == MouseEvent.MOUSE_DRAGGED)
1846           processMouseMotionEvent((MouseEvent) e);
1847         else
1848           processMouseEvent((MouseEvent) e);
1849       }
1850     else if (e instanceof ComponentEvent)
1851       processComponentEvent((ComponentEvent) e);
1852     else if (e instanceof KeyEvent)
1853       processKeyEvent((KeyEvent) e);
1854     else if (e instanceof InputMethodEvent)
1855       processInputMethodEvent((InputMethodEvent) e);
1856     else if (e instanceof HierarchyEvent)
1857       {
1858         if (e.id == HierarchyEvent.HIERARCHY_CHANGED)
1859           processHierarchyEvent((HierarchyEvent) e);
1860         else
1861           processHierarchyBoundsEvent((HierarchyEvent) e);
1862       }
1863   }
1864
1865   /**
1866    * Called when a component event is dispatched and component events are
1867    * enabled.  This method passes the event along to any listeners
1868    * that are attached.
1869    *
1870    * @param event The <code>ComponentEvent</code> to process.
1871    */
1872   protected void processComponentEvent(ComponentEvent e)
1873   {
1874     if (componentListener == null)
1875       return;
1876     switch (e.id)
1877       {
1878         case ComponentEvent.COMPONENT_HIDDEN:
1879           componentListener.componentHidden(e);
1880         break;
1881                 
1882         case ComponentEvent.COMPONENT_MOVED:
1883           componentListener.componentMoved(e);
1884         break;
1885         
1886         case ComponentEvent.COMPONENT_RESIZED:
1887           componentListener.componentResized(e);
1888         break;
1889         
1890         case ComponentEvent.COMPONENT_SHOWN:
1891           componentListener.componentShown(e);
1892         break;
1893       }
1894   }
1895
1896   /**
1897    * Called when a focus event is dispatched and component events are
1898    * enabled.  This method passes the event along to any listeners
1899    * that are attached.
1900    *
1901    * @param event The <code>FocusEvent</code> to process.
1902    */
1903   protected void processFocusEvent(FocusEvent e)
1904   {
1905     if (focusListener == null)
1906       return;
1907     switch (e.id)
1908       {
1909         case FocusEvent.FOCUS_GAINED:
1910           focusListener.focusGained(e);
1911         break;
1912         case FocusEvent.FOCUS_LOST:
1913           focusListener.focusLost(e);
1914         break;
1915       }    
1916   }
1917
1918   /**
1919    * Called when a key event is dispatched and component events are
1920    * enabled.  This method passes the event along to any listeners
1921    * that are attached.
1922    *
1923    * @param event The <code>KeyEvent</code> to process.
1924    */
1925   protected void processKeyEvent(KeyEvent e)
1926   {
1927     if (keyListener == null)
1928       return;
1929     switch (e.id)
1930       {
1931         case KeyEvent.KEY_PRESSED:
1932           keyListener.keyPressed(e);
1933         break;
1934         case KeyEvent.KEY_RELEASED:
1935           keyListener.keyReleased(e);
1936         break;
1937         case KeyEvent.KEY_TYPED:
1938           keyListener.keyTyped(e);
1939         break;
1940       }
1941   }
1942
1943   /**
1944    * Called when a regular mouse event is dispatched and component events are
1945    * enabled.  This method passes the event along to any listeners
1946    * that are attached.
1947    *
1948    * @param event The <code>MouseEvent</code> to process.
1949    */
1950   protected void processMouseEvent(MouseEvent e)
1951   {
1952     if (mouseListener == null)
1953       return;
1954     switch (e.id)
1955       {
1956         case MouseEvent.MOUSE_CLICKED:
1957           mouseListener.mouseClicked(e);
1958         break;
1959         case MouseEvent.MOUSE_ENTERED:
1960           mouseListener.mouseEntered(e);
1961         break;
1962         case MouseEvent.MOUSE_EXITED:
1963           mouseListener.mouseExited(e);
1964         break;
1965         case MouseEvent.MOUSE_PRESSED:
1966           mouseListener.mousePressed(e);
1967         break;
1968         case MouseEvent.MOUSE_RELEASED:
1969           mouseListener.mouseReleased(e);
1970         break;
1971       }
1972   }
1973
1974   /**
1975    * Called when a mouse motion event is dispatched and component events are
1976    * enabled.  This method passes the event along to any listeners
1977    * that are attached.
1978    *
1979    * @param event The <code>MouseMotionEvent</code> to process.
1980    */
1981   protected void processMouseMotionEvent(MouseEvent e)
1982   {
1983     if (mouseMotionListener == null)
1984       return;
1985     switch (e.id)
1986       {
1987         case MouseEvent.MOUSE_DRAGGED:
1988           mouseMotionListener.mouseDragged(e);
1989         break;
1990         case MouseEvent.MOUSE_MOVED:
1991           mouseMotionListener.mouseMoved(e);
1992         break;
1993       } 
1994   }
1995
1996   /** @since 1.2 */
1997   protected void processInputMethodEvent(InputMethodEvent e)
1998   {
1999     if (inputMethodListener == null)
2000       return;
2001     switch (e.id)
2002       {
2003         case InputMethodEvent.CARET_POSITION_CHANGED:
2004           inputMethodListener.caretPositionChanged(e);
2005         break;
2006         case InputMethodEvent.INPUT_METHOD_TEXT_CHANGED:
2007           inputMethodListener.inputMethodTextChanged(e);
2008         break;
2009       } 
2010   }
2011   
2012   /** @since 1.3 */
2013   protected void processHierarchyEvent(HierarchyEvent e)
2014   {
2015     if (hierarchyListener == null)
2016       return;
2017     if (e.id == HierarchyEvent.HIERARCHY_CHANGED)
2018       hierarchyListener.hierarchyChanged(e);
2019   }
2020   
2021   /** @since 1.3 */
2022   protected void processHierarchyBoundsEvent(HierarchyEvent e)
2023   {
2024     if (hierarchyBoundsListener == null)
2025       return;
2026     switch (e.id)
2027       {
2028         case HierarchyEvent.ANCESTOR_MOVED:
2029           hierarchyBoundsListener.ancestorMoved(e);
2030         break;
2031         case HierarchyEvent.ANCESTOR_RESIZED:
2032           hierarchyBoundsListener.ancestorResized(e);
2033         break;
2034       }
2035   }
2036
2037   private void processPaintEvent(PaintEvent event)
2038   {
2039     // Can't do graphics without peer
2040     if (peer == null)
2041       return;
2042
2043     Graphics gfx = getGraphics();
2044     Shape clip = event.getUpdateRect();
2045     gfx.setClip(clip);
2046
2047     switch (event.id)
2048       {
2049       case PaintEvent.PAINT:
2050         paint(gfx);
2051         break;
2052       case PaintEvent.UPDATE:
2053         update(gfx);
2054         break;
2055       default:
2056         throw new IllegalArgumentException("unknown paint event");
2057       }
2058   }
2059
2060   /**
2061    * AWT 1.0 event processor.
2062    *
2063    * @deprecated Deprecated in favor of <code>processEvent</code>.
2064    */
2065   public boolean handleEvent(Event evt)
2066   {
2067     return false;
2068   }
2069
2070   /**
2071    * AWT 1.0 mouse event.
2072    *
2073    * @deprecated Deprecated in favor of <code>processMouseEvent()</code>.
2074    */
2075   public boolean mouseDown(Event evt, int x, int y)
2076   {
2077     return false;
2078   }
2079   
2080   /**
2081    * AWT 1.0 mouse event.
2082    *
2083    * @deprecated Deprecated in favor of <code>processMouseMotionEvent()</code>.
2084    */
2085   public boolean mouseDrag(Event evt, int x, int y)
2086   {
2087     return false;
2088   }
2089
2090   /**
2091    * AWT 1.0 mouse event.
2092    *
2093    * @deprecated Deprecated in favor of <code>processMouseEvent()</code>.
2094    */
2095   public boolean mouseUp(Event evt, int x, int y)
2096   {
2097     return false;
2098   }
2099
2100   /**
2101    * AWT 1.0 mouse event.
2102    *
2103    * @deprecated Deprecated in favor of <code>processMouseMotionEvent()</code>.
2104    */
2105   public boolean mouseMove(Event evt, int x, int y)
2106   {
2107     return false;
2108   }
2109
2110   /**
2111    * AWT 1.0 mouse event.
2112    *
2113    * @deprecated Deprecated in favor of <code>processMouseEvent()</code>.
2114    */
2115   public boolean mouseEnter(Event evt, int x, int y)
2116   {
2117     return false;
2118   }
2119
2120   /**
2121    * AWT 1.0 mouse event.
2122    *
2123    * @deprecated Deprecated in favor of <code>processMouseEvent()</code>.
2124    */
2125   public boolean mouseExit(Event evt, int x, int y)
2126   {
2127     return false;
2128   }
2129
2130   /**
2131    * AWT 1.0 key press event.
2132    *
2133    * @deprecated Deprecated in favor of <code>processKeyEvent</code>.
2134    */
2135   public boolean keyDown(Event evt, int key)
2136   {
2137     return false;
2138   }
2139
2140   /**
2141    * AWT 1.0 key press event.
2142    *
2143    * @deprecated Deprecated in favor of <code>processKeyEvent</code>.
2144    */
2145   public boolean keyUp(Event evt, int key)
2146   {
2147     return false;
2148   }
2149
2150   /**
2151    * AWT 1.0 action event processor.
2152    *
2153    * @deprecated Deprecated in favor of the <code>ActionListener</code>
2154    * interface.
2155    */
2156   public boolean action(Event evt, Object what)
2157   {
2158     return false;
2159   }
2160
2161   /**
2162    * Called to inform this component it has been added to a container.
2163    * A native peer - if any - is created at this time.  This method is
2164    * called automatically by the AWT system and should not be called by
2165    * user level code.
2166    */
2167   public void addNotify()
2168   {
2169     if (peer == null)
2170       peer = getToolkit().createComponent(this);
2171
2172     /* Now that all the children has gotten their peers, we should
2173        have the event mask needed for this component and its
2174        lightweight subcomponents. */
2175
2176     peer.setEventMask(eventMask);
2177
2178     /* We do not invalidate here, but rather leave that job up to
2179        the peer. For efficiency, the peer can choose not to
2180        invalidate if it is happy with the current dimensions,
2181        etc. */
2182   }
2183
2184   /**
2185    * Called to inform this component is has been removed from its
2186    * container.  Its native peer - if any - is destroyed at this time.
2187    * This method is called automatically by the AWT system and should
2188    * not be called by user level code.
2189    */
2190   public void removeNotify()
2191   {    
2192     if (peer != null)
2193       peer.dispose();
2194     peer = null;
2195   }
2196   
2197   /** @deprecated */
2198   public boolean gotFocus(Event evt, Object what)
2199   {
2200     return false;
2201   }
2202   
2203   /** @deprecated */
2204   public boolean lostFocus(Event evt, Object what)
2205   {
2206     return false;
2207   }
2208
2209   /**
2210    * Tests whether or not this component is in the group that can
2211    * be traversed using the keyboard traversal mechanism (such as the TAB
2212    * key).
2213    *
2214    * @return <code>true</code> if the component is traversed via the TAB
2215    * key, <code>false</code> otherwise.
2216    */
2217   public boolean isFocusTraversable()
2218   {
2219     return enabled && visible && (peer == null || peer.isFocusTraversable ());
2220   }
2221
2222   /**
2223    * Requests that this component be given focus.  The <code>gotFocus()</code>
2224    * method on this event will be called when and if this request was
2225    * successful.
2226    */
2227   public void requestFocus()
2228   {
2229     // If there's no peer then this component can't get the focus.  We
2230     // treat it as a silent rejection of the request.
2231     if (peer != null)
2232       peer.requestFocus ();
2233   }
2234
2235   // This method is used to implement transferFocus().
2236   // CHILD is the child making the request.
2237   // This is overridden by Container; when called for an ordinary
2238   // component there is no child and so we always return null.
2239   Component findNextFocusComponent (Component child)
2240   {
2241     return null;
2242   }
2243
2244   /**
2245    * Transfers focus to the next component in the focus traversal order.
2246    */
2247   public void transferFocus()
2248   {
2249     Component next;
2250     if (parent == null)
2251       next = findNextFocusComponent (null);
2252     else
2253       next = parent.findNextFocusComponent (this);
2254     if (next != null && next != this)
2255       next.requestFocus ();
2256   }
2257
2258   /**
2259    * AWT 1.0 focus event processor.
2260    *
2261    * @deprecated Deprecated in favor of <code>transferFocus()</code>.
2262    */
2263   public void nextFocus()
2264   {
2265     transferFocus();
2266   }
2267
2268   /** @since 1.2 */
2269   public boolean hasFocus()
2270   {
2271     return hasFocus;
2272   }
2273
2274   /**
2275    * Adds the specified popup menu to this component.
2276    *
2277    * @param menu The popup menu to be added.
2278    */
2279   public synchronized void add(PopupMenu popup)
2280   {
2281     if (popups == null)
2282       popups = new Vector();
2283     popups.addElement(popup);    
2284   }
2285
2286   /**
2287    * Removes the specified popup menu from this component.
2288    *
2289    * @param menu The popup menu to remove.
2290    */
2291   public synchronized void remove(MenuComponent popup)
2292   {
2293     popups.removeElement(popup);
2294   }
2295
2296   /**
2297    * Returns a debugging string representing this component.
2298    *
2299    * @return A string representing this component.
2300    */
2301   protected String paramString()
2302   {
2303     StringBuffer param = new StringBuffer();
2304     String name = getName();
2305     if (name != null)
2306       {
2307         param.append(name);
2308         param.append(",");
2309       }
2310     param.append(width);
2311     param.append("x");
2312     param.append(height);
2313     param.append("+");
2314     param.append(x);
2315     param.append("+");
2316     param.append(y);
2317     
2318     if (!isValid())
2319       param.append(",invalid");
2320     if (!isVisible())
2321       param.append(",invisible");
2322     if (!isEnabled())
2323       param.append(",disabled");
2324     if (!isOpaque())
2325       param.append(",translucent");
2326     if (isDoubleBuffered())
2327       param.append(",doublebuffered");
2328     
2329     return param.toString();
2330   }
2331
2332   /**
2333    * Returns a string representation of this component.
2334    *
2335    * @return A string representation of this component
2336    */
2337   public String toString()
2338   {
2339     return this.getClass().getName() + "[" + paramString() + "]";
2340   }
2341
2342   /**
2343    * Prints a listing of this component to the standard output.
2344    */
2345   public void list ()
2346   {
2347     list (System.out, 0);
2348   }
2349
2350   /**
2351    * Prints a listing of this component to the specified print stream.
2352    *
2353    * @param stream The <code>PrintStream</code> to print to.
2354    */
2355   public void list (PrintStream out)
2356   {
2357     list (out, 0);
2358   }
2359
2360   /**
2361    * Prints a listing of this component to the specified print stream,
2362    * starting at the specified indentation point.
2363    *
2364    * @param stream The <code>PrintStream</code> to print to.
2365    * @param indent The indentation point.
2366    */
2367   public void list (PrintStream out, int indent)
2368   {
2369     for (int i = 0; i < indent; ++i)
2370       out.print (' ');
2371     out.println (toString ());
2372   }
2373
2374   /**
2375    * Prints a listing of this component to the specified print writer.
2376    *
2377    * @param writer The <code>PrintWrinter</code> to print to.
2378    */
2379   public void list (PrintWriter out)
2380   {
2381     list (out, 0);
2382   }
2383
2384   /**
2385    * Prints a listing of this component to the specified print writer,
2386    * starting at the specified indentation point.
2387    *
2388    * @param writer The <code>PrintWriter</code> to print to.
2389    * @param indent The indentation point.
2390    */
2391   public void list (PrintWriter out, int indent)
2392   {
2393     for (int i = 0; i < indent; ++i)
2394       out.print (' ');
2395     out.println (toString ());
2396   }
2397
2398   public void addPropertyChangeListener(PropertyChangeListener listener)
2399   {
2400     if (changeSupport == null)
2401       changeSupport = new PropertyChangeSupport(this);
2402     changeSupport.addPropertyChangeListener(listener);
2403   }
2404
2405   public void removePropertyChangeListener(PropertyChangeListener listener)
2406   {
2407     if (changeSupport != null)
2408       changeSupport.removePropertyChangeListener(listener);         
2409   }
2410
2411   public void addPropertyChangeListener(String propertyName,
2412                                         PropertyChangeListener listener)
2413   {
2414     if (changeSupport == null)
2415       changeSupport = new PropertyChangeSupport(this);
2416     changeSupport.addPropertyChangeListener(propertyName, listener);  
2417   }
2418
2419   public void removePropertyChangeListener(String propertyName,
2420                                            PropertyChangeListener listener)
2421   {
2422     if (changeSupport != null)
2423       changeSupport.removePropertyChangeListener(propertyName, listener);
2424   }
2425
2426   protected void firePropertyChange(String propertyName, Object oldValue, 
2427                                     Object newValue)
2428   {
2429     if (changeSupport != null)
2430       changeSupport.firePropertyChange(propertyName, oldValue, newValue);    
2431   }
2432
2433   public void setComponentOrientation(ComponentOrientation o)
2434   {
2435     orientation = o;
2436   }
2437
2438   public ComponentOrientation getComponentOrientation()
2439   {
2440     return orientation;
2441   }
2442
2443   /*
2444   public AccessibleContext getAccessibleContext()
2445   {
2446     return accessibleContext;
2447   }
2448   */
2449
2450 /**
2451   * AWT 1.0 focus event processor.
2452   *
2453   * @deprecated Deprecated in favor of <code>processFocusEvent</code>.
2454   
2455 public boolean
2456 gotFocus(Event event, Object what)
2457 {
2458   return(true);
2459 }
2460 */
2461
2462 /**
2463   * AWT 1.0 focus event processor.
2464   *
2465   * @deprecated Deprecated in favor of <code>processFocusEvent</code>.
2466   
2467 public boolean
2468 lostFocus(Event event, Object what)
2469 {
2470   return(true);
2471 }
2472 */
2473
2474 }