OSDN Git Service

2004-11-30 Thomas Fitzsimmons <fitzsim@redhat.com>
[pf3gnuchains/gcc-fork.git] / libjava / javax / swing / JComponent.java
1 /* JComponent.java -- Every component in swing inherits from this class.
2    Copyright (C) 2002, 2004 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37
38
39 package javax.swing;
40
41 import java.awt.AWTEvent;
42 import java.awt.Color;
43 import java.awt.Component;
44 import java.awt.Container;
45 import java.awt.Dimension;
46 import java.awt.FlowLayout;
47 import java.awt.Font;
48 import java.awt.Graphics;
49 import java.awt.Image;
50 import java.awt.Insets;
51 import java.awt.Point;
52 import java.awt.Rectangle;
53 import java.awt.event.ActionEvent;
54 import java.awt.event.ActionListener;
55 import java.awt.event.ContainerEvent;
56 import java.awt.event.ContainerListener;
57 import java.awt.event.FocusEvent;
58 import java.awt.event.FocusListener;
59 import java.awt.event.KeyEvent;
60 import java.awt.event.MouseEvent;
61 import java.awt.geom.Rectangle2D;
62 import java.awt.image.ImageObserver;
63 import java.awt.peer.LightweightPeer;
64 import java.beans.PropertyChangeEvent;
65 import java.beans.PropertyChangeListener;
66 import java.beans.PropertyVetoException;
67 import java.beans.VetoableChangeListener;
68 import java.io.Serializable;
69 import java.util.EventListener;
70 import java.util.Hashtable;
71 import java.util.Locale;
72
73 import javax.accessibility.Accessible;
74 import javax.accessibility.AccessibleContext;
75 import javax.accessibility.AccessibleRole;
76 import javax.accessibility.AccessibleStateSet;
77 import javax.swing.border.Border;
78 import javax.swing.event.AncestorListener;
79 import javax.swing.event.EventListenerList;
80 import javax.swing.event.SwingPropertyChangeSupport;
81 import javax.swing.plaf.ComponentUI;
82
83 /**
84  * Every component in swing inherits from this class (JLabel, JButton, etc).
85  * It contains generic methods to manage events, properties and sizes. Actual
86  * drawing of the component is channeled to a look-and-feel class that is
87  * implemented elsewhere.
88  *
89  * @author Ronald Veldema (rveldema&064;cs.vu.nl)
90  * @author Graydon Hoare (graydon&064;redhat.com)
91  */
92 public abstract class JComponent extends Container implements Serializable
93 {
94   private static final long serialVersionUID = -7908749299918704233L;
95
96   /** 
97    * Accessibility support is currently missing.
98    */
99
100   protected AccessibleContext accessibleContext;
101
102   public abstract class AccessibleJComponent 
103     extends AccessibleAWTContainer
104   {
105     protected class AccessibleFocusHandler 
106       implements FocusListener
107     {
108       protected AccessibleFocusHandler(){}
109       public void focusGained(FocusEvent event){}
110       public void focusLost(FocusEvent valevent){}
111     }
112
113     protected class AccessibleContainerHandler 
114       implements ContainerListener
115     {
116       protected AccessibleContainerHandler() {}
117       public void componentAdded(ContainerEvent event) {}
118       public void componentRemoved(ContainerEvent valevent) {}
119     }
120
121     private static final long serialVersionUID = -7047089700479897799L;
122   
123     protected ContainerListener accessibleContainerHandler;
124     protected FocusListener accessibleFocusHandler;
125
126     protected AccessibleJComponent() {}
127     public void addPropertyChangeListener(PropertyChangeListener listener) {}
128     public void removePropertyChangeListener(PropertyChangeListener listener) {}
129     public int getAccessibleChildrenCount() { return 0; }
130     public Accessible getAccessibleChild(int value0) { return null; }
131     public AccessibleStateSet getAccessibleStateSet() { return null; } 
132     public String getAccessibleName() { return null; }
133     public String getAccessibleDescription() { return null; }
134     public AccessibleRole getAccessibleRole() { return null; }
135     protected String getBorderTitle(Border value0) { return null; }
136   }
137
138   /** 
139    * An explicit value for the component's preferred size; if not set by a
140    * user, this is calculated on the fly by delegating to the {@link
141    * ComponentUI.getPreferredSize} method on the {@link #ui} property. 
142    */
143   Dimension preferredSize;
144
145   /** 
146    * An explicit value for the component's minimum size; if not set by a
147    * user, this is calculated on the fly by delegating to the {@link
148    * ComponentUI.getMinimumSize} method on the {@link #ui} property. 
149    */
150   Dimension minimumSize;
151
152   /** 
153    * An explicit value for the component's maximum size; if not set by a
154    * user, this is calculated on the fly by delegating to the {@link
155    * ComponentUI.getMaximumSize} method on the {@link #ui} property.
156    */
157   Dimension maximumSize;
158
159
160   /**
161    * A value between 0.0 and 1.0 indicating the preferred horizontal
162    * alignment of the component, relative to its siblings. The values
163    * {@link #LEFT_ALIGNMENT}, {@link #CENTER_ALIGNMENT}, and {@link
164    * #RIGHT_ALIGNMENT} can also be used, as synonyms for <code>0.0</code>,
165    * <code>0.5</code>, and <code>1.0</code>, respectively. Not all layout
166    * managers use this property.
167    *
168    * @see #getAlignmentX
169    * @see #setAlignmentX
170    * @see javax.swing.OverlayLayout
171    * @see javax.swing.BoxLayout
172    */
173   float alignmentX = 0.0f;
174
175   /**
176    * A value between 0.0 and 1.0 indicating the preferred vertical
177    * alignment of the component, relative to its siblings. The values
178    * {@link #TOP_ALIGNMENT}, {@link #CENTER_ALIGNMENT}, and {@link
179    * #BOTTOM_ALIGNMENT} can also be used, as synonyms for <code>0.0</code>,
180    * <code>0.5</code>, and <code>1.0</code>, respectively. Not all layout
181    * managers use this property.
182    *
183    * @see #getAlignmentY
184    * @see #setAlignmentY
185    * @see javax.swing.OverlayLayout
186    * @see javax.swing.BoxLayout
187    */
188   float alignmentY = 0.0f;
189
190   /** 
191    * The border painted around this component.
192    * 
193    * @see #paintBorder
194    */
195   Border border;
196
197   /** 
198    * The text to show in the tooltip associated with this component.
199    * 
200    * @see #setToolTipText
201    * @see #getToolTipText
202    */
203    String toolTipText;
204
205   /** 
206    * <p>Whether to double buffer this component when painting. This flag
207    * should generally be <code>false</code>, except for top level
208    * components such as {@link JFrame} or {@link JApplet}.</p>
209    *
210    * <p>All children of a double buffered component are painted into the
211    * double buffer automatically, so only the top widget in a window needs
212    * to be double buffered.</p>
213    *
214    * @see #setDoubleBuffered
215    * @see #isDoubleBuffered
216    * @see #paintLock
217    * @see #paint
218    */
219   boolean doubleBuffered = false;
220
221   /**
222    * A set of flags indicating which debugging graphics facilities should
223    * be enabled on this component. The values should be a combination of
224    * {@link DebugGraphics.NONE_OPTION}, {@link DebugGraphics.LOG_OPTION},
225    * {@link DebugGraphics.FLASH_OPTION}, or {@link
226    * DebugGraphics.BUFFERED_OPTION}.
227    *
228    * @see setDebugGraphicsOptions
229    * @see getDebugGraphicsOptions
230    * @see DebugGraphics
231    * @see getComponentGraphics
232    */
233   int debugGraphicsOptions;
234
235   /** 
236    * <p>This property controls two independent behaviors simultaneously.</p>
237    *
238    * <p>First, it controls whether to fill the background of this widget
239    * when painting its body. This affects calls to {@link
240    * JComponent#paintComponent}, which in turn calls {@link
241    * ComponentUI#update} on the component's {@link #ui} property. If the
242    * component is opaque during this call, the background will be filled
243    * before calling {@link ComponentUI#paint}. This happens merely as a
244    * convenience; you may fill the component's background yourself too,
245    * but there is no need to do so if you will be filling with the same
246    * color.</p>
247    *
248    * <p>Second, it the opaque property informs swing's repaint system
249    * whether it will be necessary to paint the components "underneath" this
250    * component, in Z-order. If the component is opaque, it is considered to
251    * completely occlude components "underneath" it, so they will not be
252    * repainted along with the opaque component.</p>
253    *
254    * <p>The default value for this property is <code>false</code>, but most
255    * components will want to set it to <code>true</code> when installing UI
256    * defaults in {@link ComponentUI#installUI}.</p>
257    *
258    * @see #setOpaque
259    * @see #isOpaque
260    * @see #paintComponent
261    */
262   boolean opaque = false;
263
264   /** 
265    * The user interface delegate for this component. Event delivery and
266    * repainting of the component are usually delegated to this object. 
267    *
268    * @see #setUI
269    * @see #getUI
270    * @see #updateUI
271    */
272   protected ComponentUI ui;
273
274   /**
275    * A hint to the focus system that this component should or should not
276    * get focus. If this is <code>false</code>, swing will not try to
277    * request focus on this component; if <code>true</code>, swing might
278    * try to request focus, but the request might fail. Thus it is only 
279    * a hint guiding swing's behavior.
280    *
281    * @see #requestFocus
282    * @see #isRequestFocusEnabled
283    * @see #setRequestFocusEnabled
284    */
285   boolean requestFocusEnabled;
286
287   /**
288    * Flag indicating behavior of this component when the mouse is dragged
289    * outside the component and the mouse <em>stops moving</em>. If
290    * <code>true</code>, synthetic mouse events will be delivered on regular
291    * timed intervals, continuing off in the direction the mouse exited the
292    * component, until the mouse is released or re-enters the component.
293    *
294    * @see setAutoscrolls
295    * @see getAutoscrolls
296    */
297   boolean autoscrolls = false;
298
299   /**
300    * Listeners for events other than {@link PropertyChangeEvent} are
301    * handled by this listener list. PropertyChangeEvents are handled in
302    * {@link #changeSupport}.
303    */
304   protected EventListenerList listenerList = new EventListenerList();
305
306   /** 
307    * Support for {@link PropertyChangeEvent} events. This is constructed
308    * lazily when the component gets its first {@link
309    * PropertyChangeListener} subscription; until then it's an empty slot.
310    */
311   private SwingPropertyChangeSupport changeSupport;
312
313
314   /** 
315    * Storage for "client properties", which are key/value pairs associated
316    * with this component by a "client", such as a user application or a
317    * layout manager. This is lazily constructed when the component gets its
318    * first client property.
319    */
320   private Hashtable clientProperties;
321   
322   private InputMap inputMap_whenFocused;
323   private InputMap inputMap_whenAncestorOfFocused;
324   private InputMap inputMap_whenInFocusedWindow;
325   private ActionMap actionMap;
326   private InputVerifier inputVerifier;
327
328   private TransferHandler transferHandler;
329
330   /** 
331    * A lock held during recursive painting; this is used to serialize
332    * access to the double buffer, and also to select the "top level" 
333    * object which should acquire the double buffer in a given widget
334    * tree (which may have multiple double buffered children).
335    *
336    * @see #doubleBuffered
337    * @see #paint
338    */
339   private static final Object paintLock = new Object();
340
341
342   /**
343    * The default locale of the component.
344    * 
345    * @see #getDefaultLocale
346    * @see #setDefaultLocale
347    */
348   private static Locale defaultLocale;
349   
350   public static final String TOOL_TIP_TEXT_KEY = "ToolTipText";
351
352   /**
353    * Constant used to indicate that no condition has been assigned to a
354    * particular action.
355    *
356    * @see #registerKeyboardAction
357    */
358   public static final int UNDEFINED_CONDITION = -1;
359
360   /**
361    * Constant used to indicate that an action should be performed only when 
362    * the component has focus.
363    *
364    * @see #registerKeyboardAction
365    */
366   public static final int WHEN_FOCUSED = 0;
367
368   /**
369    * Constant used to indicate that an action should be performed only when 
370    * the component is an ancestor of the component which has focus.
371    *
372    * @see #registerKeyboardAction
373    */
374   public static final int WHEN_ANCESTOR_OF_FOCUSED_COMPONENT = 1;
375
376   /**
377    * Constant used to indicate that an action should be performed only when 
378    * the component is in the window which has focus.
379    *
380    * @see #registerKeyboardAction
381    */
382   public static final int WHEN_IN_FOCUSED_WINDOW = 2;
383
384
385   /**
386    * Creates a new <code>JComponent</code> instance.
387    */
388   public JComponent()
389   {
390     super();
391     super.setLayout(new FlowLayout());
392     defaultLocale = Locale.getDefault();
393     debugGraphicsOptions = DebugGraphics.NONE_OPTION;
394   }
395
396   /**
397    * Helper to lazily construct and return the client properties table.
398    * 
399    * @return The current client properties table
400    *
401    * @see #clientProperties
402    * @see #getClientProperty
403    * @see #putClientProperty
404    */
405   private Hashtable getClientProperties()
406   {
407     if (clientProperties == null)
408       clientProperties = new Hashtable();
409     return clientProperties;
410   }
411
412   /**
413    * Get a client property associated with this component and a particular
414    * key.
415    *
416    * @param key The key with which to look up the client property
417    *
418    * @return A client property associated with this object and key
419    *
420    * @see #clientProperties
421    * @see #getClientProperties
422    * @see #putClientProperty
423    */
424   public Object getClientProperty(Object key)
425   {
426     return getClientProperties().get(key);
427   }
428
429   /**
430    * Add a client property <code>value</code> to this component, associated
431    * with <code>key</code>. If there is an existing client property
432    * associated with <code>key</code>, it will be replaced.
433    *
434    * @param key The key of the client property association to add
435    * @param value The value of the client property association to add
436    *
437    * @see #clientProperties
438    * @see #getClientProperties
439    * @see #getClientProperty
440    */
441   public void putClientProperty(Object key, Object value)
442   {
443     getClientProperties().put(key, value);
444   }
445
446   /**
447    * Unregister an <code>AncestorListener</code>.
448    *
449    * @param listener The listener to unregister
450    * 
451    * @see addAncestorListener
452    */
453   public void removeAncestorListener(AncestorListener listener)
454   {
455     listenerList.remove(AncestorListener.class, listener);
456   }
457
458   /**
459    * Unregister a <code>PropertyChangeListener</code>.
460    *
461    * @param listener The listener to register
462    *
463    * @see #addPropertyChangeListener
464    * @see #changeSupport
465    */
466   public void removePropertyChangeListener(PropertyChangeListener listener)
467   {
468     if (changeSupport != null)
469       changeSupport.removePropertyChangeListener(listener);
470   }
471
472   /**
473    * Unregister a <code>PropertyChangeListener</code>.
474    *
475    * @param propertyName The property name to unregister the listener from
476    * @param listener The listener to unregister
477    *
478    * @see #addPropertyChangeListener
479    * @see #changeSupport
480    */
481   public void removePropertyChangeListener(String propertyName,
482                                            PropertyChangeListener listener)
483   {
484     if (changeSupport != null)
485       changeSupport.removePropertyChangeListener(propertyName, listener);
486   }
487
488   /**
489    * Unregister a <code>VetoableChangeChangeListener</code>.
490    *
491    * @param listener The listener to unregister
492    *
493    * @see #addVetoableChangeListener
494    */
495   public void removeVetoableChangeListener(VetoableChangeListener listener)
496   {
497     listenerList.remove(VetoableChangeListener.class, listener);
498   }
499
500   /**
501    * Register an <code>AncestorListener</code>.
502    *
503    * @param listener The listener to register
504    *
505    * @see #removeVetoableChangeListener
506    */
507   public void addAncestorListener(AncestorListener listener)
508   {
509     listenerList.add(AncestorListener.class, listener);
510   }
511
512   /**
513    * Register a <code>PropertyChangeListener</code>. This listener will
514    * receive any PropertyChangeEvent, regardless of property name. To
515    * listen to a specific property name, use {@link
516    * #addPropertyChangeListener(String,PropertyChangeListener)} instead.
517    *
518    * @param listener The listener to register
519    *
520    * @see #removePropertyChangeListener
521    * @see #changeSupport
522    */
523   public void addPropertyChangeListener(PropertyChangeListener listener)
524   {
525     if (changeSupport == null)
526       changeSupport = new SwingPropertyChangeSupport(this);
527     changeSupport.addPropertyChangeListener(listener);
528   }
529
530   /**
531    * Register a <code>PropertyChangeListener</code> for a specific, named
532    * property. To listen to all property changes, regardless of name, use
533    * {@link #addPropertyChangeListener(PropertyChangeListener)} instead.
534    *
535    * @param propertyName The property name to listen to
536    * @param listener The listener to register
537    *
538    * @see #removePropertyChangeListener
539    * @see #changeSupport
540    */
541   public void addPropertyChangeListener(String propertyName,
542                                         PropertyChangeListener listener)
543   {
544     listenerList.add(PropertyChangeListener.class, listener);
545   }
546
547   /**
548    * Register a <code>VetoableChangeListener</code>.
549    *
550    * @param listener The listener to register
551    *
552    * @see #removeVetoableChangeListener
553    * @see #listenerList
554    */
555   public void addVetoableChangeListener(VetoableChangeListener listener)
556   {
557     listenerList.add(VetoableChangeListener.class, listener);
558   }
559
560   /**
561    * Return all registered listeners of a particular type.
562    *
563    * @param listenerType The type of listener to return
564    *
565    * @return All listeners in the {@link #listenerList} which 
566    * are of the specified type
567    *
568    * @see #listenerList
569    */
570   public EventListener[] getListeners(Class listenerType)
571   {
572     return listenerList.getListeners(listenerType);
573   }
574
575   /**
576    * Return all registered <code>AncestorListener</code> objects.
577    *
578    * @return The set of <code>AncestorListener</code> objects in {@link
579    * #listenerList}
580    */
581   public AncestorListener[] getAncestorListeners()
582   {
583     return (AncestorListener[]) getListeners(AncestorListener.class);
584   }
585
586   /**
587    * Return all registered <code>VetoableChangeListener</code> objects.
588    *
589    * @return The set of <code>VetoableChangeListener</code> objects in {@link
590    * #listenerList}
591    */
592   public VetoableChangeListener[] getVetoableChangeListeners()
593   {
594     return (VetoableChangeListener[]) getListeners(VetoableChangeListener.class);
595   }
596
597   /**
598    * Return all <code>PropertyChangeListener</code> objects registered to listen
599    * for a particular property.
600    *
601    * @param property The property to return the listeners of
602    *
603    * @return The set of <code>PropertyChangeListener</code> objects in 
604    * {@link #changeSupport} registered to listen on the specified propert
605    */
606   public PropertyChangeListener[] getPropertyChangeListeners(String property)
607   {
608     return changeSupport == null ? new PropertyChangeListener[0]
609                                  : changeSupport.getPropertyChangeListeners(property);
610   }
611
612   /**
613    * A variant of {@link #firePropertyChange(String,Object,Object)} 
614    * for properties with <code>boolean</code> values.
615    */
616   public void firePropertyChange(String propertyName, boolean oldValue,
617                                  boolean newValue)
618   {
619     if (changeSupport != null)
620       changeSupport.firePropertyChange(propertyName, Boolean.valueOf(oldValue),
621                                        Boolean.valueOf(newValue));
622   }
623
624   /**
625    * A variant of {@link #firePropertyChange(String,Object,Object)} 
626    * for properties with <code>byte</code> values.
627    */
628   public void firePropertyChange(String propertyName, byte oldValue,
629                                  byte newValue)
630   {
631     if (changeSupport != null)
632       changeSupport.firePropertyChange(propertyName, new Byte(oldValue),
633                                        new Byte(newValue));
634   }
635
636   /**
637    * A variant of {@link #firePropertyChange(String,Object,Object)} 
638    * for properties with <code>char</code> values.
639    */
640   public void firePropertyChange(String propertyName, char oldValue,
641                                  char newValue)
642   {
643     if (changeSupport != null)
644       changeSupport.firePropertyChange(propertyName, new Character(oldValue),
645                                        new Character(newValue));
646   }
647
648   /**
649    * A variant of {@link #firePropertyChange(String,Object,Object)} 
650    * for properties with <code>double</code> values.
651    */
652   public void firePropertyChange(String propertyName, double oldValue,
653                                  double newValue)
654   {
655     if (changeSupport != null)
656       changeSupport.firePropertyChange(propertyName, new Double(oldValue),
657                                        new Double(newValue));
658   }
659
660   /**
661    * A variant of {@link #firePropertyChange(String,Object,Object)} 
662    * for properties with <code>float</code> values.
663    */
664   public void firePropertyChange(String propertyName, float oldValue,
665                                  float newValue)
666   {
667     if (changeSupport != null)
668       changeSupport.firePropertyChange(propertyName, new Float(oldValue),
669                                        new Float(newValue));
670   }
671
672   /**
673    * A variant of {@link #firePropertyChange(String,Object,Object)} 
674    * for properties with <code>int</code> values.
675    */
676   public void firePropertyChange(String propertyName, int oldValue,
677                                  int newValue)
678   {
679     if (changeSupport != null)
680       changeSupport.firePropertyChange(propertyName, new Integer(oldValue),
681                                        new Integer(newValue));
682   }
683
684   /**
685    * A variant of {@link #firePropertyChange(String,Object,Object)} 
686    * for properties with <code>long</code> values.
687    */
688   public void firePropertyChange(String propertyName, long oldValue,
689                                  long newValue)
690   {
691     if (changeSupport != null)
692       changeSupport.firePropertyChange(propertyName, new Long(oldValue),
693                                        new Long(newValue));
694   }
695
696   /**
697    * Call {@link PropertyChangeListener#propertyChange} on all listeners
698    * registered to listen to a given property. Any method which changes
699    * the specified property of this component should call this method.
700    *
701    * @param propertyName The property which changed
702    * @param oldValue The old value of the property
703    * @param newValue The new value of the property
704    *
705    * @see #changeSupport
706    * @see #addPropertyChangeListener
707    * @see #removePropertyChangeListener
708    */
709   protected void firePropertyChange(String propertyName, Object oldValue,
710                                     Object newValue)
711   {
712     if (changeSupport != null)
713       changeSupport.firePropertyChange(propertyName, oldValue, newValue);
714   }
715
716   /**
717    * A variant of {@link #firePropertyChange(String,Object,Object)} 
718    * for properties with <code>short</code> values.
719    */
720   public void firePropertyChange(String propertyName, short oldValue,
721                                  short newValue)
722   {
723     if (changeSupport != null)
724       changeSupport.firePropertyChange(propertyName, new Short(oldValue),
725                                        new Short(newValue));
726   }
727
728   /**
729    * Call {@link VetoableChangeListener#vetoableChange} on all listeners
730    * registered to listen to a given property. Any method which changes
731    * the specified property of this component should call this method.
732    *
733    * @param propertyName The property which changed
734    * @param oldValue The old value of the property
735    * @param newValue The new value of the property
736    *
737    * @throws PropertyVetoException if the change was vetoed by a listener
738    *
739    * @see addVetoableChangeListener
740    * @see removeVetoableChangeListener
741    */
742   protected void fireVetoableChange(String propertyName, Object oldValue,
743                                     Object newValue)
744     throws PropertyVetoException
745   {
746     VetoableChangeListener[] listeners = getVetoableChangeListeners();
747     
748     PropertyChangeEvent evt = new PropertyChangeEvent(this, propertyName, oldValue, newValue);
749     
750     for (int i = 0; i < listeners.length; i++)
751       listeners[i].vetoableChange(evt);
752   }
753
754   /**
755    * Get the value of the accessibleContext property for this component.
756    *
757    * @return the current value of the property
758    */
759   public AccessibleContext getAccessibleContext()
760   {
761     return null;
762   }
763
764
765   /**
766    * Get the value of the {@link #alignmentX} property.
767    *
768    * @return The current value of the property.
769    *
770    * @see #setAlignmentX
771    * @see #alignmentY
772    */
773   public float getAlignmentX()
774   {
775     return alignmentX;
776   }
777
778   /**
779    * Get the value of the {@link #alignmentY} property.
780    *
781    * @return The current value of the property.
782    *
783    * @see #setAlignmentY
784    * @see #alignmentX
785    */
786   public float getAlignmentY()
787   {
788     return alignmentY;
789   }
790
791   /**
792    * Get the current value of the {@link #autoscrolls} property.
793    *
794    * @return The current value of the property
795    */
796   public boolean getAutoscrolls()
797   {
798     return autoscrolls;
799   }
800
801   /**
802    * Set the value of the {@link #border} property, revalidate
803    * and repaint this component.
804    *   
805    * @param newBorder The new value of the property
806    *
807    * @see #getBorder
808    */
809   public void setBorder(Border newBorder)
810   {
811     Border oldBorder = border;
812     border = newBorder;
813     firePropertyChange("border", oldBorder, newBorder);
814     revalidate();
815     repaint();
816   }
817
818   /**
819    * Get the value of the {@link #border} property.
820    *
821    * @return The property's current value
822    *
823    * @see #setBorder
824    */
825   public Border getBorder()
826   {
827     return border;
828   }
829
830   /**
831    * Get the component's current bounding box. If a rectangle is provided,
832    * use this as the return value (adjusting its fields in place);
833    * otherwise (of <code>null</code> is provided) return a new {@link
834    * Rectangle}.
835    *
836    * @param rv Optional return value to use
837    *
838    * @return A rectangle bounding the component
839    */
840   public Rectangle getBounds(Rectangle rv)
841   {
842     if (rv == null)
843       return new Rectangle(getX(), getY(), getWidth(), getHeight());
844     else
845       {
846         rv.setBounds(getX(), getY(), getWidth(), getHeight());
847         return rv;
848       }
849   }
850
851   /**
852    * Prepares a graphics context for painting this object. If {@link
853    * #debugGraphicsOptions} is not equal to {@link
854    * DebugGraphics#NONE_OPTION}, produce a new {@link DebugGraphics} object
855    * wrapping the parameter. Otherwise configure the parameter with this
856    * component's foreground color and font.
857    *
858    * @param g The graphics context to wrap or configure
859    *
860    * @return A graphics context to paint this object with
861    *
862    * @see #debugGraphicsOptions
863    * @see #paint
864    */
865   protected Graphics getComponentGraphics(Graphics g)
866   {    
867     Graphics g2 = g.create();
868     g2.setFont(this.getFont());
869     g2.setColor(this.getForeground());
870     return g2;
871   }
872
873
874   /**
875    * Get the value of the {@link #debugGraphicsOptions} property.
876    *
877    * @return The current value of the property.
878    *
879    * @see #setDebugGraphicsOptions
880    * @see #debugGraphicsOptions
881    */
882   public int getDebugGraphicsOptions()
883   {
884     return 0;
885   }
886
887   /**
888    * Get the component's insets, which are calculated from
889    * the {@link #border} property. If the border is <code>null</code>,
890    * calls {@link Container#getInsets}.
891    *
892    * @return The component's current insets
893    */
894   public Insets getInsets()
895   {
896     if (border == null)
897       return super.getInsets();
898     return getBorder().getBorderInsets(this);
899   }
900
901   /**
902    * Get the component's insets, which are calculated from the {@link
903    * #border} property. If the border is <code>null</code>, calls {@link
904    * Container#getInsets}. The passed-in {@link Insets} value will be
905    * used as the return value, if possible.
906    *
907    * @param insets Return value object to reuse, if possible
908    *
909    * @return The component's current insets
910    */
911   public Insets getInsets(Insets insets)
912   {
913     Insets t = getInsets();
914
915     if (insets == null)
916       return t;
917
918     insets.left = t.left;
919     insets.right = t.right;
920     insets.top = t.top;
921     insets.bottom = t.bottom;
922     return insets;
923   }
924
925   /**
926    * Get the component's location. The passed-in {@link Point} value
927    * will be used as the return value, if possible.
928    *
929    * @param rv Return value object to reuse, if possible
930    *
931    * @return The component's current location
932    */
933   public Point getLocation(Point rv)
934   {
935     if (rv == null)
936       return new Point(getX(), getY());
937
938     rv.setLocation(getX(), getY());
939     return rv;
940   }
941
942   /**
943    * Get the component's maximum size. If the {@link #maximumSize} property
944    * has been explicitly set, it is returned. If the {@link #maximumSize}
945    * property has not been set but the {@link ui} property has been, the
946    * result of {@link ComponentUI#getMaximumSize} is returned. If neither
947    * property has been set, the result of {@link Container#getMaximumSize}
948    * is returned.
949    *
950    * @return The maximum size of the component
951    *
952    * @see #maximumSize
953    * @see #setMaximumSize
954    */
955   public Dimension getMaximumSize()
956   {
957     if (maximumSize != null)
958       return maximumSize;
959
960     if (ui != null)
961       {
962         Dimension s = ui.getMaximumSize(this);
963         if (s != null)
964           return s;
965       }
966
967     Dimension p = super.getMaximumSize();
968     return p;
969   }
970
971   /**
972    * Get the component's minimum size. If the {@link #minimumSize} property
973    * has been explicitly set, it is returned. If the {@link #minimumSize}
974    * property has not been set but the {@link ui} property has been, the
975    * result of {@link ComponentUI#getMinimumSize} is returned. If neither
976    * property has been set, the result of {@link Container#getMinimumSize}
977    * is returned.
978    *
979    * @return The minimum size of the component
980    *
981    * @see #minimumSize
982    * @see #setMinimumSize
983    */
984   public Dimension getMinimumSize()
985   {
986     if (minimumSize != null)
987       return minimumSize;
988
989     if (ui != null)
990       {
991         Dimension s = ui.getMinimumSize(this);
992         if (s != null)
993           return s;
994       }
995
996     Dimension p = super.getMinimumSize();
997     return p;
998   }
999
1000   /**
1001    * Get the component's preferred size. If the {@link #preferredSize}
1002    * property has been explicitly set, it is returned. If the {@link
1003    * #preferredSize} property has not been set but the {@link ui} property
1004    * has been, the result of {@link ComponentUI#getPreferredSize} is
1005    * returned. If neither property has been set, the result of {@link
1006    * Container#getPreferredSize} is returned.
1007    *
1008    * @return The preferred size of the component
1009    *
1010    * @see #preferredSize
1011    * @see #setPreferredSize
1012    */
1013   public Dimension getPreferredSize()
1014   {
1015     if (preferredSize != null)
1016       return preferredSize;
1017
1018     if (ui != null)
1019       {
1020         Dimension s = ui.getPreferredSize(this);
1021         if (s != null)
1022           return s;
1023       }
1024     Dimension p = super.getPreferredSize();
1025     return p;
1026   }
1027
1028   /**
1029    * Checks if a maximum size was explicitely set on the component.
1030    *
1031    * @return <code>true</code> if a maximum size was set,
1032    * <code>false</code> otherwise
1033    * 
1034    * @since 1.3
1035    */
1036   public boolean isMaximumSizeSet()
1037   {
1038     return maximumSize != null;
1039   }
1040
1041   /**
1042    * Checks if a minimum size was explicitely set on the component.
1043    *
1044    * @return <code>true</code> if a minimum size was set,
1045    * <code>false</code> otherwise
1046    * 
1047    * @since 1.3
1048    */
1049   public boolean isMinimumSizeSet()
1050   {
1051     return minimumSize != null;
1052   }
1053
1054   /**
1055    * Checks if a preferred size was explicitely set on the component.
1056    *
1057    * @return <code>true</code> if a preferred size was set,
1058    * <code>false</code> otherwise
1059    * 
1060    * @since 1.3
1061    */
1062   public boolean isPreferredSizeSet()
1063   {
1064     return preferredSize != null;
1065   }
1066   
1067   /**
1068    * Return the value of the {@link #nextFocusableComponent} property.
1069    *
1070    * @return The current value of the property, or <code>null</code>
1071    * if none has been set.
1072    * 
1073    * @deprecated See {@link java.awt.FocusTraversalPolicy}
1074    */
1075   public Component getNextFocusableComponent()
1076   {
1077     return null;
1078   }
1079
1080   /**
1081    * Return the set of {@link KeyStroke} objects which are registered
1082    * to initiate actions on this component.
1083    *
1084    * @return An array of the registered keystrokes
1085    */
1086   public KeyStroke[] getRegisteredKeyStrokes()
1087   {
1088     return null;
1089   }
1090
1091   /**
1092    * Returns the first ancestor of this component which is a {@link JRootPane}.
1093    * Equivalent to calling <code>SwingUtilities.getRootPane(this);</code>.
1094    *
1095    * @return An ancestral JRootPane, or <code>null</code> if none exists.
1096    */
1097   public JRootPane getRootPane()
1098   {
1099     JRootPane p = SwingUtilities.getRootPane(this);
1100     return p;
1101   }
1102
1103   /**
1104    * Get the component's size. The passed-in {@link Dimension} value
1105    * will be used as the return value, if possible.
1106    *
1107    * @param rv Return value object to reuse, if possible
1108    *
1109    * @return The component's current size
1110    */
1111   public Dimension getSize(Dimension rv)
1112   {
1113     if (rv == null)
1114       return new Dimension(getWidth(), getHeight());
1115     else
1116       {
1117         rv.setSize(getWidth(), getHeight());
1118         return rv;
1119       }
1120   }
1121
1122   /**
1123    * Return the {@link #toolTip} property of this component, creating it and
1124    * setting it if it is currently <code>null</code>. This method can be
1125    * overridden in subclasses which wish to control the exact form of
1126    * tooltip created.
1127    *
1128    * @return The current toolTip
1129    */
1130   public JToolTip createToolTip()
1131   {
1132         JToolTip toolTip = new JToolTip();
1133         toolTip.setComponent(this);
1134         toolTip.setTipText(toolTipText);
1135     
1136     return toolTip;
1137   }
1138
1139   /**
1140    * Return the location at which the {@link #toolTip} property should be
1141    * displayed, when triggered by a particular mouse event. 
1142    *
1143    * @param event The event the tooltip is being presented in response to
1144    *
1145    * @return The point at which to display a tooltip, or <code>null</code>
1146    * if swing is to choose a default location.
1147    */
1148   public Point getToolTipLocation(MouseEvent event)
1149   {
1150     return null;
1151   }
1152
1153   /**
1154    * Set the value of the {@link #toolTipText} property.
1155    *
1156    * @param text The new property value
1157    *
1158    * @see #getToolTipText
1159    */
1160   public void setToolTipText(String text)
1161   {
1162     if (text == null)
1163     {
1164       ToolTipManager.sharedInstance().unregisterComponent(this);
1165       toolTipText = null;
1166       return;
1167     }
1168                 
1169     // XXX: The tip text doesn't get updated unless you set it to null
1170     // and then to something not-null. This is consistent with the behaviour
1171     // of Sun's ToolTipManager.
1172                         
1173     String oldText = toolTipText;
1174     toolTipText = text;
1175                 
1176     if (oldText == null)
1177       ToolTipManager.sharedInstance().registerComponent(this);
1178   }
1179
1180   /**
1181    * Get the value of the {@link #toolTipText} property.
1182    *
1183    * @return The current property value
1184    *
1185    * @see #setToolTipText
1186    */
1187   public String getToolTipText()
1188   {
1189     return toolTipText;
1190   }
1191
1192   /**
1193    * Get the value of the {@link #toolTipText} property, in response to a
1194    * particular mouse event.
1195    *
1196    * @param event The mouse event which triggered the tooltip
1197    *
1198    * @return The current property value
1199    *
1200    * @see #setToolTipText
1201    */
1202   public String getToolTipText(MouseEvent event)
1203   {
1204     return getToolTipText();
1205   }
1206
1207   /**
1208    * Return the top level ancestral container (usually a {@link
1209    * java.awt.Window} or {@link java.awt.Applet}) which this component is
1210    * contained within, or <code>null</code> if no ancestors exist.
1211    *
1212    * @return The top level container, if it exists
1213    */
1214   public Container getTopLevelAncestor()
1215   {
1216     Container c = getParent();
1217     for (Container peek = c; peek != null; peek = peek.getParent())
1218       c = peek;
1219     return c;
1220   }
1221
1222   /**
1223    * Compute the component's visible rectangle, which is defined
1224    * recursively as either the component's bounds, if it has no parent, or
1225    * the intersection of the component's bounds with the visible rectangle
1226    * of its parent.
1227    *
1228    * @param rect The return value slot to place the visible rectangle in
1229    */
1230   public void computeVisibleRect(Rectangle rect)
1231   {
1232     Component c = getParent();
1233     if (c != null && c instanceof JComponent)
1234       {
1235         ((JComponent) c).computeVisibleRect(rect);
1236         rect.translate(-getX(), -getY());
1237         Rectangle2D.intersect(rect,
1238                               new Rectangle(0, 0, getWidth(), getHeight()),
1239                               rect);
1240       }
1241     else
1242       rect.setRect(0, 0, getWidth(), getHeight());
1243   }
1244
1245   /**
1246    * Return the component's visible rectangle in a new {@link Rectangle},
1247    * rather than via a return slot.
1248    *
1249    * @return The component's visible rectangle
1250    *
1251    * @see #computeVisibleRect(Rectangle)
1252    */
1253   public Rectangle getVisibleRect()
1254   {
1255     Rectangle r = new Rectangle();
1256     computeVisibleRect(r);
1257     return r;
1258   }
1259
1260   /**
1261    * <p>Requests that this component receive input focus, giving window
1262    * focus to the top level ancestor of this component. Only works on
1263    * displayable, focusable, visible components.</p>
1264    *
1265    * <p>This method should not be called by clients; it is intended for
1266    * focus implementations. Use {@link Component#requestFocus} instead.</p>
1267    *
1268    * @see {@link Component#requestFocus}
1269    */
1270   public void grabFocus()
1271   {
1272   }
1273
1274   /**
1275    * Get the value of the {@link #doubleBuffered} property.
1276    *
1277    * @return The property's current value
1278    */
1279   public boolean isDoubleBuffered()
1280   {
1281     return doubleBuffered;
1282   }
1283
1284   /**
1285    * Return <code>true</code> if the provided component has no native peer;
1286    * in other words, if it is a "lightweight component".
1287    *
1288    * @param c The component to test for lightweight-ness
1289    *
1290    * @return Whether or not the component is lightweight
1291    */
1292   public static boolean isLightweightComponent(Component c)
1293   {
1294     return c.getPeer() instanceof LightweightPeer;
1295   }
1296
1297   /**
1298    * Return <code>true<code> if you wish this component to manage its own
1299    * focus. In particular: if you want this component to be sent
1300    * <code>TAB</code> and <code>SHIFT+TAB</code> key events, and to not
1301    * have its children considered as focus transfer targets. If
1302    * <code>true</code>, focus traversal around this component changes to
1303    * <code>CTRL+TAB</code> and <code>CTRL+SHIFT+TAB</code>.
1304    *
1305    * @return <code>true</code> if you want this component to manage its own
1306    * focus, otherwise (by default) <code>false</code>
1307    *
1308    * @deprecated 1.4 Use {@link Component.setFocusTraversalKeys(int,Set)} and
1309    * {@link Container.setFocusCycleRoot(boolean)} instead
1310    */
1311   public boolean isManagingFocus()
1312   {
1313     return false;
1314   }
1315
1316   /**
1317    * Return the current value of the {@link opaque} property. 
1318    *
1319    * @return The current property value
1320    */
1321   public boolean isOpaque()
1322   {
1323     return opaque;
1324   }
1325
1326   /**
1327    * Return <code>true</code> if the component can guarantee that none of its
1328    * children will overlap in Z-order. This is a hint to the painting system.
1329    * The default is to return <code>true</code>, but some components such as
1330    * {@link JLayeredPane} should override this to return <code>false</code>.
1331    *
1332    * @return Whether the component tiles its children
1333    */
1334   public boolean isOptimizedDrawingEnabled()
1335   {
1336     return true;
1337   }
1338
1339   /**
1340    * Return <code>true</code> if this component is currently painting a tile.
1341    *
1342    * @return Whether the component is painting a tile
1343    */
1344   public boolean isPaintingTile()
1345   {
1346     return false;
1347   }
1348
1349   /**
1350    * Get the value of the {@link #requestFocusEnabled} property.
1351    *
1352    * @return The current value of the property
1353    */
1354   public boolean isRequestFocusEnabled()
1355   {
1356     return requestFocusEnabled;
1357   }
1358
1359   /**
1360    * Return <code>true</code> if this component is a validation root; this
1361    * will cause calls to {@link #invalidate} in this component's children
1362    * to be "captured" at this component, and not propagate to its parents.
1363    * For most components this should return <code>false</code>, but some
1364    * components such as {@link JViewPort} will want to return
1365    * <code>true</code>.
1366    *
1367    * @return Whether this component is a validation root
1368    */
1369   public boolean isValidateRoot()
1370   {
1371     return false;
1372   }
1373
1374   /**
1375    * <p>Paint the component. This is a delicate process, and should only be
1376    * called from the repaint thread, under control of the {@link
1377    * RepaintManager}. Client code should usually call {@link #repaint} to
1378    * trigger painting.</p>
1379    *
1380    * <p>This method will acquire a double buffer from the {@link
1381    * RepaintManager} if the component's {@link #doubleBuffered} property is
1382    * <code>true</code> and the <code>paint</code> call is the
1383    * <em>first</em> recursive <code>paint</code> call inside swing.</p>
1384    *
1385    * <p>The method will also modify the provided {@link Graphics} context
1386    * via the {@link #getComponentGraphics} method. If you want to customize
1387    * the graphics object used for painting, you should override that method
1388    * rather than <code>paint</code>.</p>
1389    *
1390    * <p>The body of the <code>paint</code> call involves calling {@link
1391    * #paintComponent}, {@link #paintBorder}, and {@link #paintChildren} in
1392    * order. If you want to customize painting behavior, you should override
1393    * one of these methods rather than <code>paint</code>.</p>
1394    *
1395    * <p>For more details on the painting sequence, see <a
1396    * href="http://java.sun.com/products/jfc/tsc/articles/painting/index.html">this
1397    * article</a>.</p>
1398    *
1399    * @param g The graphics context to paint with
1400    *
1401    * @see #paintImmediately
1402    */
1403   public void paint(Graphics g)
1404   {
1405     Graphics g2 = g;
1406     Image doubleBuffer = null;
1407     RepaintManager rm = RepaintManager.currentManager(this);
1408
1409     if (isDoubleBuffered()
1410         && (rm.isDoubleBufferingEnabled())
1411         && (! Thread.holdsLock(paintLock)))
1412       {
1413         doubleBuffer = rm.getOffscreenBuffer(this, getWidth(), getHeight());
1414       }
1415
1416     synchronized (paintLock)
1417       {
1418         if (doubleBuffer != null)
1419           {
1420             g2 = doubleBuffer.getGraphics();
1421             g2.setClip(g.getClipBounds());
1422           }
1423           
1424         g2 = getComponentGraphics(g2);
1425         paintComponent(g2);
1426         paintBorder(g2);
1427         paintChildren(g2);
1428         
1429         if (doubleBuffer != null)
1430           g.drawImage(doubleBuffer, 0, 0, (ImageObserver) null);
1431       }
1432   }
1433
1434   /**
1435    * Paint the component's border. This usually means calling {@link
1436    * Border#paintBorder} on the {@link #border} property, if it is
1437    * non-<code>null</code>. You may override this if you wish to customize
1438    * border painting behavior. The border is painted after the component's
1439    * body, but before the component's children.
1440    *
1441    * @param g The graphics context with which to paint the border
1442    *
1443    * @see #paint
1444    * @see #paintChildren
1445    * @see #paintComponent
1446    */
1447   protected void paintBorder(Graphics g)
1448   {
1449     if (getBorder() != null)
1450       getBorder().paintBorder(this, g, 0, 0, getWidth(), getHeight());
1451   }
1452
1453   /**
1454    * Paint the component's children. This usually means calling {@link
1455    * Container#paint}, which recursively calls {@link #paint} on any of the
1456    * component's children, with appropriate changes to coordinate space and
1457    * clipping region. You may override this if you wish to customize
1458    * children painting behavior. The children are painted after the
1459    * component's body and border.
1460    *
1461    * @param g The graphics context with which to paint the children
1462    *
1463    * @see #paint
1464    * @see #paintBorder
1465    * @see #paintComponent
1466    */
1467   protected void paintChildren(Graphics g)
1468   {
1469     super.paint(g);
1470   }
1471
1472   /**
1473    * Paint the component's body. This usually means calling {@link
1474    * ComponentUI#update} on the {@link #ui} property of the component, if
1475    * it is non-<code>null</code>. You may override this if you wish to
1476    * customize the component's body-painting behavior. The component's body
1477    * is painted first, before the border and children.
1478    *
1479    * @param g The graphics context with which to paint the body
1480    *
1481    * @see #paint
1482    * @see #paintBorder
1483    * @see #paintChildren
1484    */
1485   protected void paintComponent(Graphics g)
1486   {
1487     if (ui != null)
1488       ui.update(g, this);
1489   }
1490
1491   /**
1492    * A variant of {@link #paintImmediately(Rectangle)} which takes
1493    * integer parameters.
1494    *
1495    * @param x The left x coordinate of the dirty region
1496    * @param y The top y coordinate of the dirty region
1497    * @param w The width of the dirty region
1498    * @param h The height of the dirty region
1499    */
1500   public void paintImmediately(int x, int y, int w, int h)
1501   {
1502     paintImmediately(new Rectangle(x, y, w, h));
1503   }
1504
1505   /**
1506    * Transform the provided dirty rectangle for this component into the
1507    * appropriate ancestral {@link JRootPane} and call {@link #paint} on
1508    * that root pane. This method is called from the {@link RepaintManager}
1509    * and should always be called within the painting thread.
1510    *
1511    * @param r The dirty rectangle to paint
1512    */
1513   public void paintImmediately(Rectangle r)
1514   {
1515     Component root = SwingUtilities.getRoot(this);
1516     if (root == null || ! root.isShowing())
1517       return;
1518     Graphics g = root.getGraphics();
1519     if (g == null)
1520       return;
1521
1522     Rectangle clip = SwingUtilities.convertRectangle(this, r, root);
1523     g.setClip(clip);
1524     root.paint(g);
1525     g.dispose();
1526   }
1527
1528   /**
1529    * Return a string representation for this component, for use in
1530    * debugging.
1531    *
1532    * @return A string describing this component.
1533    */
1534   protected String paramString()
1535   {
1536     return "JComponent";
1537   }
1538
1539   /**
1540    * A variant of {@link
1541    * #registerKeyboardAction(ActionListener,String,KeyStroke,int)} which
1542    * provides <code>null</code> for the command name.   
1543    */
1544   public void registerKeyboardAction(ActionListener act,
1545                                      KeyStroke stroke, 
1546                                      int cond)
1547   {
1548     registerKeyboardAction(act, null, stroke, cond);
1549   }
1550
1551   /* 
1552    * There is some charmingly undocumented behavior sun seems to be using
1553    * to simulate the old register/unregister keyboard binding API. It's not
1554    * clear to me why this matters, but we shall endeavour to follow suit.
1555    *
1556    * Two main thing seem to be happening when you do registerKeyboardAction():
1557    * 
1558    *  - no actionMap() entry gets created, just an entry in inputMap()
1559    *
1560    *  - the inputMap() entry is a proxy class which invokes the the
1561    *  binding's actionListener as a target, and which clobbers the command
1562    *  name sent in the ActionEvent, providing the binding command name
1563    *  instead.
1564    *
1565    * This much you can work out just by asking the input and action maps
1566    * what they contain after making bindings, and watching the event which
1567    * gets delivered to the recipient. Beyond that, it seems to be a
1568    * sun-private solution so I will only immitate it as much as it matters
1569    * to external observers.
1570    */
1571
1572   private static class ActionListenerProxy
1573     extends AbstractAction
1574   {
1575     ActionListener target;
1576     String bindingCommandName;
1577
1578     public ActionListenerProxy(ActionListener li, 
1579                                String cmd)
1580     {
1581       target = li;
1582       bindingCommandName = cmd;
1583     }
1584
1585     public void actionPerformed(ActionEvent e)
1586     {
1587       ActionEvent derivedEvent = new ActionEvent(e.getSource(),
1588                                                  e.getID(),
1589                                                  bindingCommandName,
1590                                                  e.getModifiers());
1591       target.actionPerformed(derivedEvent);
1592     }
1593   }
1594
1595   
1596   /**
1597    * An obsolete method to register a keyboard action on this component.
1598    * You should use <code>getInputMap</code> and <code>getActionMap</code>
1599    * to fetch mapping tables from keystrokes to commands, and commands to
1600    * actions, respectively, and modify those mappings directly.
1601    *
1602    * @param anAction The action to be registered
1603    * @param aCommand The command to deliver in the delivered {@link
1604    * java.awt.ActionEvent}
1605    * @param aKeyStroke The keystroke to register on
1606    * @param aCondition One of the values {@link #UNDEFINED_CONDITION},
1607    * {@link #WHEN_ANCESTOR_OF_FOCUSED_COMPONENT}, {@link #WHEN_FOCUSED}, or
1608    * {@link #WHEN_IN_FOCUSED_WINDOW}, indicating the condition which must
1609    * be met for the action to be fired
1610    *
1611    * @see #unregisterKeyboardAction
1612    * @see #getConditionForKeystroke
1613    * @see #resetKeyboardActiond
1614    */
1615   public void registerKeyboardAction(ActionListener act, 
1616                                      String cmd,
1617                                      KeyStroke stroke, 
1618                                      int cond)
1619   {
1620     getInputMap(cond).put(stroke, new ActionListenerProxy(act, cmd));
1621   }
1622
1623
1624
1625   public final void setInputMap(int condition, InputMap map)
1626   {
1627     enableEvents(AWTEvent.KEY_EVENT_MASK);
1628     switch (condition)
1629       {
1630       case WHEN_FOCUSED:
1631         inputMap_whenFocused = map;
1632         break;
1633
1634       case WHEN_ANCESTOR_OF_FOCUSED_COMPONENT:
1635         inputMap_whenAncestorOfFocused = map;
1636         break;
1637
1638       case WHEN_IN_FOCUSED_WINDOW:
1639         inputMap_whenInFocusedWindow = map;
1640         break;
1641         
1642       case UNDEFINED_CONDITION:
1643       default:
1644         throw new IllegalArgumentException();
1645       }
1646   }
1647
1648   public final InputMap getInputMap(int condition)
1649   {
1650     enableEvents(AWTEvent.KEY_EVENT_MASK);
1651     switch (condition)
1652       {
1653       case WHEN_FOCUSED:
1654         if (inputMap_whenFocused == null)
1655           inputMap_whenFocused = new InputMap();
1656         return inputMap_whenFocused;
1657
1658       case WHEN_ANCESTOR_OF_FOCUSED_COMPONENT:
1659         if (inputMap_whenAncestorOfFocused == null)
1660           inputMap_whenAncestorOfFocused = new InputMap();
1661         return inputMap_whenAncestorOfFocused;
1662
1663       case WHEN_IN_FOCUSED_WINDOW:
1664         if (inputMap_whenInFocusedWindow == null)
1665           inputMap_whenInFocusedWindow = new InputMap();
1666         return inputMap_whenInFocusedWindow;
1667
1668       case UNDEFINED_CONDITION:
1669       default:
1670         return null;
1671       }
1672   }
1673
1674   public final InputMap getInputMap()
1675   {
1676     return getInputMap(WHEN_FOCUSED);
1677   }
1678
1679   public final ActionMap getActionMap()
1680   {
1681     if (actionMap == null)
1682       actionMap = new ActionMap();
1683     return actionMap;
1684   }
1685
1686   public final void setActionMap(ActionMap map)
1687   {
1688     actionMap = map;
1689   }
1690
1691   /**
1692    * Return the condition that determines whether a registered action
1693    * occurs in response to the specified keystroke.
1694    *
1695    * @param aKeyStroke The keystroke to return the condition of
1696    *
1697    * @return One of the values {@link #UNDEFINED_CONDITION}, {@link
1698    * #WHEN_ANCESTOR_OF_FOCUSED_COMPONENT}, {@link #WHEN_FOCUSED}, or {@link
1699    * #WHEN_IN_FOCUSED_WINDOW}
1700    *
1701    * @deprecated As of 1.3 KeyStrokes can be registered with multiple
1702    * simultaneous conditions.
1703    *
1704    * @see #registerKeyboardAction   
1705    * @see #unregisterKeyboardAction   
1706    * @see #resetKeyboardActiond
1707    */
1708   public int getConditionForKeyStroke(KeyStroke ks)
1709   {
1710     if (inputMap_whenFocused != null 
1711         && inputMap_whenFocused.get(ks) != null)
1712       return WHEN_FOCUSED;
1713     else if (inputMap_whenAncestorOfFocused != null 
1714              && inputMap_whenAncestorOfFocused.get(ks) != null)
1715       return WHEN_ANCESTOR_OF_FOCUSED_COMPONENT;
1716     else if (inputMap_whenInFocusedWindow != null 
1717              && inputMap_whenInFocusedWindow.get(ks) != null)
1718       return WHEN_IN_FOCUSED_WINDOW;
1719     else
1720       return UNDEFINED_CONDITION;
1721   }
1722
1723   /**
1724    * Get the ActionListener (typically an {@link Action} object) which is
1725    * associated with a particular keystroke. 
1726    *
1727    * @param aKeyStroke The keystroke to retrieve the action of
1728    *
1729    * @return The action associated with the specified keystroke
1730    *
1731    * @deprecated Use {@link #getActionMap()}
1732    */
1733   public ActionListener getActionForKeyStroke(KeyStroke ks)
1734   {
1735     Object cmd = getInputMap().get(ks);
1736     if (cmd != null)
1737       {
1738         if (cmd instanceof ActionListenerProxy)
1739           return (ActionListenerProxy) cmd;
1740         else if (cmd instanceof String)
1741           return getActionMap().get(cmd);
1742       }
1743     return null;
1744   }
1745
1746   /**
1747    * A hook for subclasses which want to customize event processing.
1748    */
1749   protected void processComponentKeyEvent(KeyEvent e)
1750   {
1751   }
1752
1753   /**
1754    * Override the default key dispatch system from Component to hook into
1755    * the swing {@link InputMap} / {@link ActionMap} system.
1756    *
1757    * See <a
1758    * href="http://java.sun.com/products/jfc/tsc/special_report/kestrel/keybindings.html">this
1759    * report</a> for more details, it's somewhat complex.
1760    */
1761   protected void processKeyEvent(KeyEvent e)
1762   {
1763     processComponentKeyEvent(e);
1764
1765     // FIXME: this needs to be elaborated significantly, to do all the
1766     // focus / ancestor / window searching for the various binding modes.
1767     if (! e.isConsumed() &&
1768         processKeyBinding(KeyStroke.getKeyStrokeForEvent(e), 
1769                           e, WHEN_FOCUSED, e.getID() == KeyEvent.KEY_PRESSED))
1770       e.consume();
1771   }
1772
1773   protected boolean processKeyBinding(KeyStroke ks,
1774                                       KeyEvent e,
1775                                       int condition,
1776                                       boolean pressed)
1777   { 
1778     if (isEnabled())
1779       {
1780         Action act = null;
1781         InputMap map = getInputMap(condition);
1782         if (map != null)
1783           {
1784             Object cmd = map.get(ks);
1785             if (cmd != null)
1786               {
1787                 if (cmd instanceof ActionListenerProxy)
1788                   act = (Action) cmd;
1789                 else 
1790                   act = (Action) getActionMap().get(cmd);
1791               }
1792           }
1793         if (act != null && act.isEnabled())
1794           return SwingUtilities.notifyAction(act, ks, e, this, e.getModifiers());
1795       }
1796     return false;
1797   }
1798   
1799   /**
1800    * Remove a keyboard action registry.
1801    *
1802    * @param stroke The keystroke to unregister
1803    *
1804    * @see #registerKeyboardAction
1805    * @see #getConditionForKeystroke
1806    * @see #resetKeyboardActiond
1807    */
1808   public void unregisterKeyboardAction(KeyStroke aKeyStroke)
1809   {
1810   }
1811
1812
1813   /**
1814    * Reset all keyboard action registries.
1815    *
1816    * @see #registerKeyboardAction
1817    * @see #unregisterKeyboardAction
1818    * @see #getConditionForKeystroke
1819    */
1820   public void resetKeyboardActions()
1821   {
1822     if (inputMap_whenFocused != null)
1823       inputMap_whenFocused.clear();
1824     if (inputMap_whenAncestorOfFocused != null)
1825       inputMap_whenAncestorOfFocused.clear();
1826     if (inputMap_whenInFocusedWindow != null)
1827       inputMap_whenInFocusedWindow.clear();
1828     if (actionMap != null)
1829       actionMap.clear();
1830   }
1831
1832
1833   /**
1834    * Mark the described region of this component as dirty in the current
1835    * {@link RepaintManager}. This will queue an asynchronous repaint using
1836    * the system painting thread in the near future.
1837    *
1838    * @param tm ignored
1839    * @param x coordinate of the region to mark as dirty
1840    * @param y coordinate of the region to mark as dirty
1841    * @param width dimension of the region to mark as dirty
1842    * @param height dimension of the region to mark as dirty
1843    */
1844   public void repaint(long tm, int x, int y, int width, int height)
1845   {
1846     Rectangle dirty = new Rectangle(x, y, width, height);
1847     Rectangle vis = getVisibleRect();
1848     dirty = dirty.intersection(vis);
1849     RepaintManager.currentManager(this).addDirtyRegion(this, dirty.x, dirty.y,
1850                                                        dirty.width,
1851                                                        dirty.height);
1852   }
1853
1854   /**
1855    * Mark the described region of this component as dirty in the current
1856    * {@link RepaintManager}. This will queue an asynchronous repaint using
1857    * the system painting thread in the near future.
1858    *
1859    * @param r The rectangle to mark as dirty
1860    */
1861   public void repaint(Rectangle r)
1862   {
1863     repaint((long) 0, (int) r.getX(), (int) r.getY(), (int) r.getWidth(),
1864             (int) r.getHeight());
1865   }
1866
1867   /**
1868    * Request focus on the default component of this component's {@link
1869    * FocusTraversalPolicy}.
1870    *
1871    * @return The result of {@link #requestFocus}
1872    *
1873    * @deprecated Use {@link #requestFocus()} on the default component provided from
1874    * the {@link FocusTraversalPolicy} instead.
1875    */
1876   public boolean requestDefaultFocus()
1877   {
1878     return false;
1879   }
1880
1881   /**
1882    * Queue a an invalidation and revalidation of this component, using 
1883    * {@link RepaintManager#addInvalidComponent}.
1884    */
1885   public void revalidate()
1886   {
1887     invalidate();
1888     RepaintManager.currentManager(this).addInvalidComponent(this);
1889   }
1890
1891   /**
1892    * Calls <code>scrollRectToVisible</code> on the component's parent. 
1893    * Components which can service this call should override.
1894    *
1895    * @param r The rectangle to make visible
1896    */
1897   public void scrollRectToVisible(Rectangle r)
1898   {
1899     Component p = getParent();
1900     if (p instanceof JComponent)
1901       ((JComponent) p).scrollRectToVisible(r);
1902   }
1903
1904   /**
1905    * Set the value of the {@link #alignmentX} property.
1906    *
1907    * @param a The new value of the property
1908    */
1909   public void setAlignmentX(float a)
1910   {
1911     alignmentX = a;
1912   }
1913
1914   /**
1915    * Set the value of the {@link #alignmentY} property.
1916    *
1917    * @param a The new value of the property
1918    */
1919   public void setAlignmentY(float a)
1920   {
1921     alignmentY = a;
1922   }
1923
1924   /**
1925    * Set the value of the {@link #autoscrolls} property.
1926    *
1927    * @param a The new value of the property
1928    */
1929   public void setAutoscrolls(boolean a)
1930   {
1931     autoscrolls = a;
1932   }
1933
1934   /**
1935    * Set the value of the {@link #debugGraphicsOptions} property.
1936    *
1937    * @param debugOptions The new value of the property
1938    */
1939   public void setDebugGraphicsOptions(int debugOptions)
1940   {
1941     debugGraphicsOptions = debugOptions;
1942   }
1943
1944   /**
1945    * Set the value of the {@link #doubleBuffered} property.
1946    *
1947    * @param db The new value of the property
1948    */
1949   public void setDoubleBuffered(boolean db)
1950   {
1951     doubleBuffered = db;
1952   }
1953
1954   /**
1955    * Set the value of the {@link #enabled} property, revalidate
1956    * and repaint this component.
1957    *
1958    * @param enable The new value of the property
1959    */
1960   public void setEnabled(boolean enable)
1961   {
1962     boolean oldEnabled = isEnabled();
1963     super.setEnabled(enable);
1964     firePropertyChange("enabeld", oldEnabled, enable);
1965     revalidate();
1966     repaint();
1967   }
1968
1969   /**
1970    * Set the value of the {@link #font} property, revalidate
1971    * and repaint this component.
1972    *
1973    * @param f The new value of the property
1974    */
1975   public void setFont(Font f)
1976   {
1977     super.setFont(f);
1978     revalidate();
1979     repaint();
1980   }
1981
1982   /**
1983    * Set the value of the {@link #background} property, revalidate
1984    * and repaint this component.
1985    *
1986    * @param bg The new value of the property
1987    */
1988   public void setBackground(Color bg)
1989   {
1990     super.setBackground(bg);
1991     revalidate();
1992     repaint();
1993   }
1994
1995   /**
1996    * Set the value of the {@link #foreground} property, revalidate
1997    * and repaint this component.
1998    *
1999    * @param fg The new value of the property
2000    */
2001   public void setForeground(Color fg)
2002   {
2003     super.setForeground(fg);
2004     revalidate();
2005     repaint();
2006   }
2007
2008   /**
2009    * Set the value of the {@link #maximumSize} property, revalidate
2010    * and repaint this component.
2011    *
2012    * @param max The new value of the property
2013    */
2014   public void setMaximumSize(Dimension max)
2015   {
2016     Dimension oldMaximumSize = maximumSize;
2017     maximumSize = max;
2018     firePropertyChange("maximumSize", oldMaximumSize, maximumSize);
2019     revalidate();
2020     repaint();
2021   }
2022
2023   /**
2024    * Set the value of the {@link #minimumSize} property, revalidate
2025    * and repaint this component.
2026    *
2027    * @param min The new value of the property
2028    */
2029   public void setMinimumSize(Dimension min)
2030   {
2031     Dimension oldMinimumSize = minimumSize;
2032     minimumSize = min;
2033     firePropertyChange("minimumSize", oldMinimumSize, minimumSize);
2034     revalidate();
2035     repaint();
2036   }
2037
2038   /**
2039    * Set the value of the {@link #preferredSize} property, revalidate
2040    * and repaint this component.
2041    *
2042    * @param pref The new value of the property
2043    */
2044   public void setPreferredSize(Dimension pref)
2045   {
2046     Dimension oldPreferredSize = preferredSize;
2047     preferredSize = pref;
2048     firePropertyChange("preferredSize", oldPreferredSize, preferredSize);
2049   }
2050
2051   /**
2052    * Set the specified component to be the next component in the 
2053    * focus cycle, overriding the {@link FocusTraversalPolicy} for
2054    * this component.
2055    *
2056    * @param aComponent The component to set as the next focusable
2057    *
2058    * @deprecated Use FocusTraversalPolicy instead
2059    */
2060   public void setNextFocusableComponent(Component aComponent)
2061   {
2062   }
2063
2064   /**
2065    * Set the value of the {@link #requestFocusEnabled} property.
2066    *
2067    * @param e The new value of the property
2068    */
2069   public void setRequestFocusEnabled(boolean e)
2070   {
2071     requestFocusEnabled = e;
2072   }
2073
2074   /**
2075    * Get the value of the {@link #transferHandler} property.
2076    *
2077    * @return The current value of the property
2078    *
2079    * @see ComponentUI#setTransferHandler
2080    */
2081
2082   public TransferHandler getTransferHandler()
2083   {
2084     return transferHandler;
2085   }
2086
2087   /**
2088    * Set the value of the {@link #transferHandler} property.
2089    *
2090    * @param newHandler The new value of the property
2091    *
2092    * @see ComponentUI#getTransferHandler
2093    */
2094
2095   void setTransferHandler (TransferHandler newHandler)
2096   {
2097     transferHandler = newHandler;
2098   }
2099
2100   /**
2101    * Set the value of the {@link #opaque} property, revalidate and repaint
2102    * this component.
2103    *
2104    * @param isOpaque The new value of the property
2105    *
2106    * @see ComponentUI#update
2107    */
2108   public void setOpaque(boolean isOpaque)
2109   {
2110     boolean oldOpaque = opaque;
2111     opaque = isOpaque;
2112     firePropertyChange("opaque", oldOpaque, opaque);
2113     revalidate();
2114     repaint();
2115   }
2116
2117   /**
2118    * Set the value of the visible property, and revalidate / repaint the
2119    * component.
2120    *
2121    * @param v The new value of the property
2122    */
2123   public void setVisible(boolean v)
2124   {
2125     super.setVisible(v);
2126     revalidate();
2127     repaint();
2128   }
2129
2130   /**
2131    * Call {@link paint}. 
2132    * 
2133    * @param g The graphics context to paint into
2134    */
2135   public void update(Graphics g)
2136   {
2137     paint(g);
2138   }
2139
2140   /**
2141    * Get the value of the UIClassID property. This property should be a key
2142    * in the {@link UIDefaults} table managed by {@link UIManager}, the
2143    * value of which is the name of a class to load for the component's
2144    * {@link ui} property.
2145    *
2146    * @return A "symbolic" name which will map to a class to use for the
2147    * component's UI, such as <code>"ComponentUI"</code>
2148    *
2149    * @see #setUI
2150    * @see #updateUI
2151    */
2152   public String getUIClassID()
2153   {
2154     return "ComponentUI";
2155   }
2156
2157   /**
2158    * Install a new UI delegate as the component's {@link ui} property. In
2159    * the process, this will call {@link ComponentUI.uninstallUI} on any
2160    * existing value for the {@link ui} property, and {@link
2161    * ComponentUI.installUI} on the new UI delegate.
2162    *
2163    * @param newUI The new UI delegate to install
2164    *
2165    * @see #updateUI
2166    * @see #getUIClassID
2167    */
2168   protected void setUI(ComponentUI newUI)
2169   {
2170     if (ui != null)
2171       ui.uninstallUI(this);
2172
2173     ComponentUI oldUI = ui;
2174     ui = newUI;
2175
2176     if (ui != null)
2177       ui.installUI(this);
2178
2179     firePropertyChange("UI", oldUI, newUI);
2180     
2181     revalidate();
2182     repaint();
2183   }
2184
2185   /**
2186    * This method should be overridden in subclasses. In JComponent, the
2187    * method does nothing. In subclasses, it should a UI delegate
2188    * (corresponding to the symbolic name returned from {@link
2189    * getUIClassID}) from the {@link UIManager}, and calls {@link setUI}
2190    * with the new delegate.
2191    */
2192   public void updateUI()
2193   {
2194     System.out.println("update UI not overwritten in class: " + this);
2195   }
2196
2197   public static Locale getDefaultLocale()
2198   {
2199     return defaultLocale;
2200   }
2201   
2202   public static void setDefaultLocale(Locale l)
2203   {
2204     defaultLocale = l;
2205   }
2206   
2207   /**
2208    * Returns the currently set input verifier for this component.
2209    *
2210    * @return the input verifier, or <code>null</code> if none
2211    */
2212   public InputVerifier getInputVerifier()
2213   {
2214     return inputVerifier;
2215   }
2216
2217   /**
2218    * Sets the input verifier to use by this component.
2219    *
2220    * @param verifier the input verifier, or <code>null</code>
2221    */
2222   public void setInputVerifier(InputVerifier verifier)
2223   {
2224     InputVerifier oldVerifier = inputVerifier;
2225     inputVerifier = verifier;
2226     firePropertyChange("inputVerifier", oldVerifier, verifier);
2227   }
2228 }