OSDN Git Service

* javax/swing/RepaintManager.java
[pf3gnuchains/gcc-fork.git] / libjava / javax / swing / AbstractButton.java
1 /* AbstractButton.java -- Provides basic button functionality.
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 package javax.swing;
39
40 import java.awt.Graphics;
41 import java.awt.Image;
42 import java.awt.Insets;
43 import java.awt.ItemSelectable;
44 import java.awt.Point;
45 import java.awt.Rectangle;
46 import java.awt.event.ActionEvent;
47 import java.awt.event.ActionListener;
48 import java.awt.event.FocusEvent;
49 import java.awt.event.FocusListener;
50 import java.awt.event.ItemEvent;
51 import java.awt.event.ItemListener;
52 import java.beans.PropertyChangeEvent;
53 import java.beans.PropertyChangeListener;
54 import java.util.EventListener;
55
56 import javax.accessibility.AccessibleAction;
57 import javax.accessibility.AccessibleIcon;
58 import javax.accessibility.AccessibleRelationSet;
59 import javax.accessibility.AccessibleStateSet;
60 import javax.accessibility.AccessibleText;
61 import javax.accessibility.AccessibleValue;
62 import javax.swing.event.ChangeEvent;
63 import javax.swing.event.ChangeListener;
64 import javax.swing.plaf.ButtonUI;
65 import javax.swing.text.AttributeSet;
66
67
68 /**
69  * <p>The purpose of this class is to serve as a facade over a number of
70  * classes which collectively represent the semantics of a button: the
71  * button's model, its listeners, its action, and its look and feel. Some
72  * parts of a button's state are stored explicitly in this class, other
73  * parts are delegates to the model. Some methods related to buttons are
74  * implemented in this class, other methods pass through to the current 
75  * model or look and feel.</p>
76  *
77  * <p>Furthermore this class is supposed to serve as a base class for
78  * several kinds of buttons with similar but non-identical semantics:
79  * toggle buttons (radio buttons and checkboxes), simple "push" buttons,
80  * menu items.</p>
81  *
82  * <p>Buttons have many properties, some of which are stored in this class
83  * while others are delegated to the button's model. The following properties
84  * are available:</p>
85  *
86  * <table>
87  * <tr><th>Property               </th><th>Stored in</th><th>Bound?</th></tr>
88  *
89  * <tr><td>action                 </td><td>button</td> <td>no</td></tr>
90  * <tr><td>actionCommand          </td><td>model</td>  <td>no</td></tr>
91  * <tr><td>borderPainted          </td><td>button</td> <td>yes</td></tr>
92  * <tr><td>contentAreaFilled      </td><td>button</td> <td>yes</td></tr>
93  * <tr><td>disabledIcon           </td><td>button</td> <td>yes</td></tr>
94  * <tr><td>disabledSelectedIcon   </td><td>button</td> <td>yes</td></tr>
95  * <tr><td>displayedMnemonicIndex </td><td>button</td> <td>no</td></tr>
96  * <tr><td>enabled                </td><td>model</td>  <td>no</td></tr>
97  * <tr><td>focusPainted           </td><td>button</td> <td>yes</td></tr>
98  * <tr><td>horizontalAlignment    </td><td>button</td> <td>yes</td></tr>
99  * <tr><td>horizontalTextPosition </td><td>button</td> <td>yes</td></tr>
100  * <tr><td>icon                   </td><td>button</td> <td>yes</td></tr>
101  * <tr><td>iconTextGap            </td><td>button</td> <td>no</td></tr>
102  * <tr><td>label (same as text)   </td><td>model</td>  <td>yes</td></tr>
103  * <tr><td>margin                 </td><td>button</td> <td>yes</td></tr>
104  * <tr><td>multiClickThreshold    </td><td>button</td> <td>no</td></tr>
105  * <tr><td>pressedIcon            </td><td>button</td> <td>yes</td></tr>
106  * <tr><td>rolloverEnabled        </td><td>button</td> <td>yes</td></tr>
107  * <tr><td>rolloverIcon           </td><td>button</td> <td>yes</td></tr>
108  * <tr><td>rolloverSelectedIcon   </td><td>button</td> <td>yes</td></tr>
109  * <tr><td>selected               </td><td>model</td>  <td>no</td></tr>
110  * <tr><td>selectedIcon           </td><td>button</td> <td>yes</td></tr>
111  * <tr><td>selectedObjects        </td><td>button</td> <td>no</td></tr>
112  * <tr><td>text                   </td><td>model</td>  <td>yes</td></tr>
113  * <tr><td>UI                     </td><td>button</td> <td>yes</td></tr>
114  * <tr><td>verticalAlignment      </td><td>button</td> <td>yes</td></tr>
115  * <tr><td>verticalTextPosition   </td><td>button</td> <td>yes</td></tr>
116  *
117  * </table>
118  *
119  * <p>The various behavioral aspects of these properties follows:</p>
120  *
121  * <ul> 
122  *
123  * <li>When non-bound properties stored in the button change, the button
124  * fires ChangeEvents to its ChangeListeners.</li>
125  * 
126  * <li>When bound properties stored in the button change, the button fires
127  * PropertyChangeEvents to its PropertyChangeListeners</li>
128  *
129  * <li>If any of the model's properties change, it fires a ChangeEvent to
130  * its ChangeListeners, which include the button.</li>
131  *
132  * <li>If the button receives a ChangeEvent from its model, it will
133  * propagate the ChangeEvent to its ChangeListeners, with the ChangeEvent's
134  * "source" property set to refer to the button, rather than the model. The
135  * the button will request a repaint, to paint its updated state.</li>
136  *
137  * <li>If the model's "selected" property changes, the model will fire an
138  * ItemEvent to its ItemListeners, which include the button, in addition to
139  * the ChangeEvent which models the property change. The button propagates
140  * ItemEvents directly to its ItemListeners.</li>
141  *
142  * <li>If the model's armed and pressed properties are simultaneously
143  * <code>true</code>, the model will fire an ActionEvent to its
144  * ActionListeners, which include the button. The button will propagate
145  * this ActionEvent to its ActionListeners, with the ActionEvent's "source"
146  * property set to refer to the button, rather than the model.</li>
147  *
148  * </ul>
149  *
150  * @author Ronald Veldema (rveldema@cs.vu.nl)
151  * @author Graydon Hoare (graydon@redhat.com)
152  */
153
154 public abstract class AbstractButton extends JComponent
155   implements ItemSelectable, SwingConstants
156 {
157   /** The icon displayed by default. */
158   Icon default_icon;
159
160   /** The icon displayed when the button is pressed. */
161   Icon pressed_icon;
162
163   /** The icon displayed when the button is disabled. */
164   Icon disabled_icon;
165
166   /** The icon displayed when the button is selected. */
167   Icon selected_icon;
168
169   /** The icon displayed when the button is selected but disabled. */
170   Icon disabled_selected_icon;
171
172   /** The icon displayed when the button is rolled over. */
173   Icon rollover_icon;
174
175   /** The icon displayed when the button is selected and rolled over. */
176   Icon rollover_selected_icon;
177
178   /** The icon currently displayed. */
179   Icon current_icon;
180
181   /** The text displayed in the button. */
182   String text;
183
184   /** The vertical alignment of the button's text and icon. */
185   int vert_align;
186
187   /** The horizontal alignment of the button's text and icon. */
188   int hori_align;
189
190   /** The horizontal position of the button's text relative to its icon. */
191   int hori_text_pos;
192
193   /** The vertical position of the button's text relative to its icon. */
194   int vert_text_pos;
195
196   /** Whether or not the button paints its border. */
197   boolean paint_border;
198
199   /** Whether or not the button paints its focus state. */
200   boolean paint_focus;
201
202   /** Whether or not the button fills its content area. */
203   boolean content_area_filled;
204
205   /** The action taken when the button is clicked. */
206   Action action;
207
208   /** The button's current state. */
209   ButtonModel model;
210
211   /** The margin between the button's border and its label. */
212   Insets margin;
213
214   /** a hint to the look and feel class, suggesting which character in the
215    * button's label should be underlined when drawing the label. */
216   int mnemonicIndex;
217
218   /** Listener the button uses to receive ActionEvents from its model.  */
219   ActionListener actionListener;
220
221   /** Listener the button uses to receive ItemEvents from its model.  */
222   ItemListener itemListener;
223
224   /** Listener the button uses to receive ChangeEvents from its model.  */  
225   ChangeListener changeListener;
226
227   /** Listener the button uses to receive PropertyChangeEvents from its
228       Action. */
229   PropertyChangeListener actionPropertyChangeListener;
230   
231   /** Fired in a PropertyChangeEvent when the "borderPainted" property changes. */
232   public static final String BORDER_PAINTED_CHANGED_PROPERTY = "borderPainted";
233   
234   /** Fired in a PropertyChangeEvent when the "contentAreaFilled" property changes. */
235   public static final String CONTENT_AREA_FILLED_CHANGED_PROPERTY = "contentAreaFilled";
236   
237   /** Fired in a PropertyChangeEvent when the "disabledIcon" property changes. */
238   public static final String DISABLED_ICON_CHANGED_PROPERTY = "disabledIcon";
239   
240   /** Fired in a PropertyChangeEvent when the "disabledSelectedIcon" property changes. */
241   public static final String DISABLED_SELECTED_ICON_CHANGED_PROPERTY = "disabledSelectedIcon";
242   
243   /** Fired in a PropertyChangeEvent when the "focusPainted" property changes. */
244   public static final String FOCUS_PAINTED_CHANGED_PROPERTY = "focusPainted";
245
246   /** Fired in a PropertyChangeEvent when the "horizontalAlignment" property changes. */
247   public static final String HORIZONTAL_ALIGNMENT_CHANGED_PROPERTY = "horizontalAlignment";
248
249   /** Fired in a PropertyChangeEvent when the "horizontalTextPosition" property changes. */
250   public static final String HORIZONTAL_TEXT_POSITION_CHANGED_PROPERTY = "horizontalTextPosition";
251
252   /** Fired in a PropertyChangeEvent when the "icon" property changes. */
253   public static final String ICON_CHANGED_PROPERTY = "icon";
254
255   /** Fired in a PropertyChangeEvent when the "margin" property changes. */
256   public static final String MARGIN_CHANGED_PROPERTY = "margin";
257
258   /** Fired in a PropertyChangeEvent when the "mnemonic" property changes. */
259   public static final String MNEMONIC_CHANGED_PROPERTY = "mnemonic";
260
261   /** Fired in a PropertyChangeEvent when the "model" property changes. */
262   public static final String MODEL_CHANGED_PROPERTY = "model";
263
264   /** Fired in a PropertyChangeEvent when the "pressedIcon" property changes. */
265   public static final String PRESSED_ICON_CHANGED_PROPERTY = "pressedIcon";
266
267   /** Fired in a PropertyChangeEvent when the "rolloverEnabled" property changes. */
268   public static final String ROLLOVER_ENABLED_CHANGED_PROPERTY = "rolloverEnabled";
269
270   /** Fired in a PropertyChangeEvent when the "rolloverIcon" property changes. */
271   public static final String ROLLOVER_ICON_CHANGED_PROPERTY = "rolloverIcon";
272   
273   /** Fired in a PropertyChangeEvent when the "rolloverSelectedIcon" property changes. */
274   public static final String ROLLOVER_SELECTED_ICON_CHANGED_PROPERTY = "rolloverSelectedIcon";
275   
276   /** Fired in a PropertyChangeEvent when the "selectedIcon" property changes. */
277   public static final String SELECTED_ICON_CHANGED_PROPERTY = "selectedIcon";
278
279   /** Fired in a PropertyChangeEvent when the "text" property changes. */
280   public static final String TEXT_CHANGED_PROPERTY = "text";
281
282   /** Fired in a PropertyChangeEvent when the "verticalAlignment" property changes. */
283   public static final String VERTICAL_ALIGNMENT_CHANGED_PROPERTY = "verticalAlignment";
284
285   /** Fired in a PropertyChangeEvent when the "verticalTextPosition" property changes. */
286   public static final String VERTICAL_TEXT_POSITION_CHANGED_PROPERTY = "verticalTextPosition";
287
288     /**
289    * A Java Accessibility extension of the AbstractButton.
290      */
291   protected abstract class AccessibleAbstractButton
292     extends AccessibleJComponent implements AccessibleAction, AccessibleValue,
293                                             AccessibleText
294   {
295     protected AccessibleAbstractButton(JComponent c)
296     {
297       super(c);
298     }
299
300     public AccessibleStateSet getAccessibleStateSet()
301     {
302       return null; // TODO
303     }
304
305     public String getAccessibleName()
306     {
307       return null; // TODO
308     }
309
310     public AccessibleIcon[] getAccessibleIcon()
311     {
312       return null; // TODO
313     }
314
315     public AccessibleRelationSet getAccessibleRelationSet()
316     {
317       return null; // TODO
318     }
319
320     public AccessibleAction getAccessibleAction()
321     {
322       return null; // TODO
323     }
324
325     public AccessibleValue getAccessibleValue()
326     {
327       return null; // TODO
328     }
329
330     public int getAccessibleActionCount()
331     {
332       return 0; // TODO
333     }
334
335     public String getAccessibleActionDescription(int value0)
336     {
337       return null; // TODO
338     }
339
340     public boolean doAccessibleAction(int value0)
341     {
342       return false; // TODO
343     }
344
345     public Number getCurrentAccessibleValue()
346     {
347       return null; // TODO
348     }
349
350     public boolean setCurrentAccessibleValue(Number value0)
351     {
352       return false; // TODO
353     }
354
355     public Number getMinimumAccessibleValue()
356     {
357       return null; // TODO
358     }
359
360     public Number getMaximumAccessibleValue()
361     {
362       return null; // TODO
363     }
364
365     public AccessibleText getAccessibleText()
366     {
367       return null; // TODO
368     }
369
370     public int getIndexAtPoint(Point value0)
371     {
372       return 0; // TODO
373     }
374
375     public Rectangle getCharacterBounds(int value0)
376     {
377       return null; // TODO
378     }
379
380     public int getCharCount()
381     {
382       return 0; // TODO
383     }
384
385     public int getCaretPosition()
386     {
387       return 0; // TODO
388     }
389
390     public String getAtIndex(int value0, int value1)
391     {
392       return null; // TODO
393     }
394
395     public String getAfterIndex(int value0, int value1)
396     {
397       return null; // TODO
398     }
399
400     public String getBeforeIndex(int value0, int value1)
401     {
402       return null; // TODO
403     }
404
405     public AttributeSet getCharacterAttribute(int value0)
406     {
407       return null; // TODO
408     }
409
410     public int getSelectionStart()
411     {
412       return 0; // TODO
413     }
414
415     public int getSelectionEnd()
416     {
417       return 0; // TODO
418     }
419
420     public String getSelectedText()
421   {
422       return null; // TODO
423     }
424
425     private Rectangle getTextRectangle()
426     {
427       return null; // TODO
428     }
429     }
430
431   /**
432    * Helper class used to subscribe to FocusEvents received by the button.
433    */
434   private class ButtonFocusListener implements FocusListener
435     {
436     /**
437      * Possibly repaint the model in response to loss of focus.
438      *
439      * @param event The loss-of-focus event
440      */
441     public void focusLost(FocusEvent event)
442         {
443       if (AbstractButton.this.isFocusPainted())
444         AbstractButton.this.repaint();
445     }
446
447     /**
448      * Possibly repaint the button in response to acquisition of focus.
449      *
450      * @param event The gained-focus event
451      */
452     public void focusGained(FocusEvent event)
453     {
454       if (AbstractButton.this.isFocusPainted())
455         AbstractButton.this.repaint();
456     }
457   }
458
459   /**
460    * Creates a new AbstractButton object.
461    */
462   AbstractButton()
463   {
464     this("",null);
465   }
466
467   /**
468    * Creates a new AbstractButton object.
469    *
470    * @param txt Value to use for the button's "text" property
471    * @param icon Value to use for the button's "defaultIcon" property
472    */
473   AbstractButton(String txt, Icon icon)
474   {
475     text = txt;
476     default_icon = icon;
477     model = new DefaultButtonModel();
478     actionListener = createActionListener();
479     changeListener = createChangeListener();
480     itemListener = createItemListener();
481
482     model.addActionListener(actionListener);
483     model.addChangeListener(changeListener);
484     model.addItemListener(itemListener);
485
486     hori_align = CENTER;
487     hori_text_pos = TRAILING;
488     vert_align = CENTER;
489     vert_text_pos = CENTER;
490     paint_border = true;
491     content_area_filled = true;
492
493     setAlignmentX(LEFT_ALIGNMENT);
494     setAlignmentY(CENTER_ALIGNMENT);
495
496     addFocusListener(new ButtonFocusListener());
497     updateUI();
498   }
499
500   /**
501    * Get the model the button is currently using.
502    *
503    * @return The current model
504    */
505   public ButtonModel getModel()
506   {
507     return model;
508   }
509
510   /**
511    * Set the model the button is currently using. This un-registers all 
512    * listeners associated with the current model, and re-registers them
513    * with the new model.
514    *
515    * @param newModel The new model
516    */
517   public void setModel(ButtonModel newModel)
518   {
519     if (newModel == model)
520       return;
521
522     if (model != null)
523       {
524         model.removeActionListener(actionListener);
525         model.removeChangeListener(changeListener);
526         model.removeItemListener(itemListener);
527       }
528     ButtonModel old = model;
529     model = newModel;
530     if (model != null)
531       {
532         model.addActionListener(actionListener);
533         model.addChangeListener(changeListener);
534         model.addItemListener(itemListener);
535       }
536     firePropertyChange(MODEL_CHANGED_PROPERTY, old, model);
537     revalidate();
538     repaint();
539   }
540
541   /**
542    * Get the action command string for this button's model.
543    *
544    * @return The current action command string from the button's model
545    */
546   public String getActionCommand()
547   {
548     return getModel().getActionCommand();
549   }
550
551   /**
552    * Set the action command string for this button's model.
553    *
554    * @param aCommand The new action command string to set in the button's
555    * model.
556    */
557   public void setActionCommand(String aCommand)
558   {
559     getModel().setActionCommand(aCommand);
560   }
561
562   /**
563    * Adds an ActionListener to the button's listener list. When the
564    * button's model is clicked it fires an ActionEvent, and these
565    * listeners will be called.
566    *
567    * @param l The new listener to add
568    */
569   public void addActionListener(ActionListener l)
570   {
571     listenerList.add(ActionListener.class, l);
572   }
573
574   /**
575    * Removes an ActionListener from the button's listener list.
576    *
577    * @param l The listener to remove
578    */
579   public void removeActionListener(ActionListener l)
580   {
581     listenerList.remove(ActionListener.class, l);
582   }
583
584   /**
585    * Adds an ItemListener to the button's listener list. When the button's
586    * model changes state (between any of ARMED, ENABLED, PRESSED, ROLLOVER
587    * or SELECTED) it fires an ItemEvent, and these listeners will be
588    * called.
589    *
590    * @param l The new listener to add
591    */
592   public void addItemListener(ItemListener l)
593   {
594     listenerList.add(ItemListener.class, l);
595   }
596
597   /**
598    * Removes an ItemListener from the button's listener list.
599    *
600    * @param l The listener to remove
601    */
602   public void removeItemListener(ItemListener l)
603   {
604     listenerList.remove(ItemListener.class, l);
605   }
606
607   /**
608    * Adds a ChangeListener to the button's listener list. When the button's
609    * model changes any of its (non-bound) properties, these listeners will be
610    * called. 
611    *
612    * @param l The new listener to add
613    */
614   public void addChangeListener(ChangeListener l)
615   {
616     listenerList.add(ChangeListener.class, l);
617   }
618
619   /**
620    * Removes a ChangeListener from the button's listener list.
621    *
622    * @param l The listener to remove
623    */
624   public void removeChangeListener(ChangeListener l)
625   {
626     listenerList.remove(ChangeListener.class, l);
627   }
628
629   /**
630    * Calls {@link ItemListener.itemStateChanged} on each ItemListener in
631    * the button's listener list.
632    *
633    * @param e The event signifying that the button's model changed state
634    */
635   public void fireItemStateChanged(ItemEvent e)
636   {
637     EventListener[] ll = listenerList.getListeners(ItemListener.class);
638     for (int i = 0; i < ll.length; i++)
639       ((ItemListener)ll[i]).itemStateChanged(e);
640   }
641
642   /**
643    * Calls {@link ActionListener.actionPerformed} on each {@link
644    * ActionListener} in the button's listener list.
645    *
646    * @param e The event signifying that the button's model was clicked
647    */
648   public void fireActionPerformed(ActionEvent e)
649   {
650     EventListener[] ll = listenerList.getListeners(ActionListener.class);
651     for (int i = 0; i < ll.length; i++)
652       ((ActionListener)ll[i]).actionPerformed(e);
653   }
654
655   /**
656    * Calls {@link ChangeEvent.stateChanged} on each {@link ChangeListener}
657    * in the button's listener list.
658    *
659    * @param e The event signifying a change in one of the (non-bound)
660    * properties of the button's model.
661    */
662   public void fireStateChanged(ChangeEvent e)
663   {
664     EventListener[] ll = listenerList.getListeners(ChangeListener.class);
665     for (int i = 0; i < ll.length; i++)
666       ((ChangeListener)ll[i]).stateChanged(e);
667   }
668
669   /**
670    * Get the current keyboard mnemonic value. This value corresponds to a
671    * single key code (one of the {@link java.awt.event.KeyEvent} VK_*
672    * codes) and is used to activate the button when pressed in conjunction
673    * with the "mouseless modifier" of the button's look and feel class, and
674    * when focus is in one of the button's ancestors.
675    *
676    * @return The button's current keyboard mnemonic
677    */
678   public int getMnemonic()
679   {
680     return getModel().getMnemonic();
681   }
682
683   /**
684    * Set the current keyboard mnemonic value. This value corresponds to a
685    * single key code (one of the {@link java.awt.event.KeyEvent} VK_*
686    * codes) and is used to activate the button when pressed in conjunction
687    * with the "mouseless modifier" of the button's look and feel class, and
688    * when focus is in one of the button's ancestors.
689    *
690    * @param mne A new mnemonic to use for the button
691    */
692   public void setMnemonic(char mne)
693   {
694     int old = getModel().getMnemonic();
695     getModel().setMnemonic(mne);
696     if (old != getModel().getMnemonic())
697       {
698         firePropertyChange(MNEMONIC_CHANGED_PROPERTY, old, (int) mne);        
699         revalidate();
700         repaint();
701       }
702   }
703
704   /**
705    * Set the current keyboard mnemonic value. This value corresponds to a
706    * single key code (one of the {@link java.awt.event.KeyEvent} VK_*
707    * codes) and is used to activate the button when pressed in conjunction
708    * with the "mouseless modifier" of the button's look and feel class, and
709    * when focus is in one of the button's ancestors.
710    *
711    * @param mne A new mnemonic to use for the button
712    */
713   public void setMnemonic(int mne)
714   {
715     int old = mne;
716     getModel().setMnemonic(mne);
717     if (old != getModel().getMnemonic())
718       {
719         firePropertyChange(MNEMONIC_CHANGED_PROPERTY, old, mne);
720         revalidate();
721         repaint();
722       }
723   }
724
725   /** 
726    * Sets the button's mnemonic index. The mnemonic index is a hint to the
727    * look and feel class, suggesting which character in the button's label
728    * should be underlined when drawing the label. If the mnemonic index is
729    * -1, no mnemonic will be displayed. 
730    * 
731    * If no mnemonic index is set, the button will choose a mnemonic index
732    * by default, which will be the first occurrence of the mnemonic
733    * character in the button's text.
734    *
735    * @param index An offset into the "text" property of the button
736    * @throws IllegalArgumentException If <code>index</code> is not within the
737    * range of legal offsets for the "text" property of the button.
738    * @since 1.4
739    */
740
741   public void setDisplayedMnemonicIndex(int index)
742   {
743     if (index < -1 || index >= text.length())
744       throw new IllegalArgumentException();
745     else
746       mnemonicIndex = index;
747   }
748   
749   /** 
750    * Get the button's mnemonic index, which is an offset into the button's
751    * "text" property.  The character specified by this offset should be
752    * underlined when the look and feel class draws this button.
753    *
754    * @return An index into the button's "text" property
755    */
756   public int getDisplayedMnemonicIndex(int index)
757   {
758     return mnemonicIndex;
759   }
760   
761
762   /**
763    * Set the "rolloverEnabled" property. When rollover is enabled, and the
764    * look and feel supports it, the button will change its icon to
765    * rollover_icon, when the mouse passes over it.
766    *
767    * @param r Whether or not to enable rollover icon changes
768    */
769   public void setRolloverEnabled(boolean r)
770   {
771     boolean old = getModel().isRollover();
772     getModel().setRollover(r);
773     if (old != getModel().isRollover())
774   {
775         firePropertyChange(ROLLOVER_ENABLED_CHANGED_PROPERTY, old, r);
776         revalidate();
777         repaint();
778       }
779   }
780
781   /**
782    * Returns whether or not rollover icon changes are enabled on the
783    * button.
784    *
785    * @return The state of the "rolloverEnabled" property
786    */
787   public boolean isRolloverEnabled()
788   {
789     return getModel().isRollover();
790   }
791
792   /**
793    * Set the value of the button's "selected" property. Selection is only
794    * meaningful for toggle-type buttons (check boxes, radio buttons).
795    *
796    * @param s New value for the property
797    */
798   public void setSelected(boolean s)
799   {
800     getModel().setSelected(s);
801   }
802
803   /**
804    * Get the value of the button's "selected" property. Selection is only
805    * meaningful for toggle-type buttons (check boxes, radio buttons).
806    *
807    * @return The value of the property
808    */
809   public boolean isSelected()
810   {
811     return getModel().isSelected();
812   }
813
814   /**
815    * Enables or disables the button. A button will neither be selectable
816    * nor preform any actions unless it is enabled.
817    *
818    * @param b Whether or not to enable the button
819    */
820   public void setEnabled(boolean b)
821   {
822     super.setEnabled(b);
823     getModel().setEnabled(b);
824   }
825
826   /** 
827    * Set the horizontal alignment of the button's text and icon. The
828    * alignment is a numeric constant from {@link SwingConstants}. It must
829    * be one of: <code>RIGHT</code>, <code>LEFT</code>, <code>CENTER</code>,
830    * <code>LEADING</code> or <code>TRAILING</code>.  The default is
831    * <code>RIGHT</code>.
832    * 
833    * @return The current horizontal alignment
834    */
835   public int getHorizontalAlignment()
836   {
837     return hori_align;
838   }
839
840   /**
841    * Set the horizontal alignment of the button's text and icon. The
842    * alignment is a numeric constant from {@link SwingConstants}. It must
843    * be one of: <code>RIGHT</code>, <code>LEFT</code>, <code>CENTER</code>,
844    * <code>LEADING</code> or <code>TRAILING</code>.  The default is
845    * <code>RIGHT</code>.
846    *
847    * @param a The new horizontal alignment
848    * @throws IllegalArgumentException If alignment is not one of the legal
849    * constants.
850    */
851   public void setHorizontalAlignment(int a)
852   {
853     int old = hori_align;
854     hori_align = a;
855     if (old != a)
856       {
857         firePropertyChange(HORIZONTAL_ALIGNMENT_CHANGED_PROPERTY, old, a);
858         revalidate();
859         repaint();
860       }
861   }
862
863   /**
864    * Get the horizontal position of the button's text relative to its
865    * icon. The position is a numeric constant from {@link
866    * SwingConstants}. It must be one of: <code>RIGHT</code>,
867    * <code>LEFT</code>, <code>CENTER</code>, <code>LEADING</code> or
868    * <code>TRAILING</code>.  The default is <code>TRAILING</code>.
869    *
870    * @return The current horizontal text position
871    */
872   public int getHorizontalTextPosition()
873   {
874     return hori_text_pos;
875   }
876
877   /**
878    * Set the horizontal position of the button's text relative to its
879    * icon. The position is a numeric constant from {@link
880    * SwingConstants}. It must be one of: <code>RIGHT</code>,
881    * <code>LEFT</code>, <code>CENTER</code>, <code>LEADING</code> or
882    * <code>TRAILING</code>. The default is <code>TRAILING</code>.
883    *
884    * @param t The new horizontal text position
885    * @throws IllegalArgumentException If position is not one of the legal
886    * constants.
887    */
888   public void setHorizontalTextPosition(int t)
889   {
890     int old = hori_text_pos;
891     hori_text_pos = t;
892     if (old != t)
893       {
894         firePropertyChange(HORIZONTAL_TEXT_POSITION_CHANGED_PROPERTY, old, t);
895         revalidate();
896         repaint();
897       }
898   }
899
900   /**
901    * Get the vertical alignment of the button's text and icon. The
902    * alignment is a numeric constant from {@link SwingConstants}. It must
903    * be one of: <code>CENTER</code>, <code>TOP</code>, or
904    * <code>BOTTOM</code>. The default is <code>CENTER</code>.
905    *
906    * @return The current vertical alignment
907    */
908   public int getVerticalAlignment()
909   {
910     return vert_align;
911   }
912
913   /**
914    * Set the vertical alignment of the button's text and icon. The
915    * alignment is a numeric constant from {@link SwingConstants}. It must
916    * be one of: <code>CENTER</code>, <code>TOP</code>, or
917    * <code>BOTTOM</code>. The default is <code>CENTER</code>.
918    *
919    * @param a The new vertical alignment
920    * @throws IllegalArgumentException If alignment is not one of the legal
921    * constants.
922    */
923   public void setVerticalAlignment(int a)
924   {
925     int old = vert_align;
926     vert_align = a;
927     if (old != a)
928       {
929         firePropertyChange(VERTICAL_ALIGNMENT_CHANGED_PROPERTY, old, a);
930         revalidate();
931         repaint();
932       }
933   }
934
935   /**
936    * Get the vertical position of the button's text relative to its
937    * icon. The alignment is a numeric constant from {@link
938    * SwingConstants}. It must be one of: <code>CENTER</code>,
939    * <code>TOP</code>, or <code>BOTTOM</code>. The default is
940    * <code>CENTER</code>.
941    *
942    * @return The current vertical position
943    */
944   public int getVerticalTextPosition()
945   {
946     return vert_text_pos;
947   }
948
949   /**
950    * Set the vertical position of the button's text relative to its
951    * icon. The alignment is a numeric constant from {@link
952    * SwingConstants}. It must be one of: <code>CENTER</code>,
953    * <code>TOP</code>, or <code>BOTTOM</code>. The default is
954    * <code>CENTER</code>.
955    *
956    * @param t The new vertical position
957    * @throws IllegalArgumentException If position is not one of the legal
958    * constants.
959    */
960   public void setVerticalTextPosition(int t)
961   {
962     int old = vert_text_pos;
963     vert_text_pos = t;
964     if (old != t)
965       {
966         firePropertyChange(VERTICAL_TEXT_POSITION_CHANGED_PROPERTY, old, t);
967         revalidate();
968         repaint();
969       }
970   }
971
972   /**
973    * Set the value of the "borderPainted" property. If set to
974    * <code>false</code>, the button's look and feel class should not paint
975    * a border for the button. The default is <code>true</code>.
976    *
977    * @return The current value of the property.
978    */
979   public boolean isBorderPainted()
980   {
981     return paint_border;
982   }
983
984   /**
985    * Set the value of the "borderPainted" property. If set to
986    * <code>false</code>, the button's look and feel class should not paint
987    * a border for the button. The default is <code>true</code>.
988    *
989    * @param b The new value of the property.
990    */
991   public void setBorderPainted(boolean b)
992   {
993     boolean old = paint_border;
994         paint_border = b;
995     if (b != old)
996       {
997         firePropertyChange(BORDER_PAINTED_CHANGED_PROPERTY, old, b);
998         revalidate();
999         repaint();
1000       }
1001   }
1002
1003   /**
1004    * Get the value of the "action" property. 
1005    *
1006    * @return The current value of the "action" property
1007    */
1008   public Action getAction()
1009   {
1010     return action;
1011   }
1012
1013   /**
1014    * <p>Set the button's "action" property, subscribing the new action to the
1015    * button, as an ActionListener, if it is not already subscribed. The old
1016    * Action, if it exists, is unsubscribed, and the button is unsubscribed
1017    * from the old Action if it was previously subscribed as a
1018    * PropertyChangeListener.</p>
1019    *
1020    * <p>This method also configures several of the button's properties from
1021    * the Action, by calling {@link configurePropertiesFromAction}, and
1022    * subscribes the button to the Action as a PropertyChangeListener.
1023    * Subsequent changes to the Action will thus reconfigure the button 
1024    * automatically.</p>
1025    *
1026    * @param a The new value of the "action" property
1027    */
1028   public void setAction(Action a)
1029   {
1030     if (action != null)
1031       {
1032         action.removePropertyChangeListener(actionPropertyChangeListener);
1033         removeActionListener(action);
1034         if (actionPropertyChangeListener != null)
1035           {
1036             action.removePropertyChangeListener(actionPropertyChangeListener);
1037             actionPropertyChangeListener = null;
1038           }
1039         actionPropertyChangeListener = createActionPropertyChangeListener(a);
1040   }
1041
1042     Action old = action;
1043     action = a;
1044     configurePropertiesFromAction(action);
1045
1046     if (action != null)
1047       {
1048         action.addPropertyChangeListener(actionPropertyChangeListener);
1049         addActionListener(action);
1050       }
1051   }
1052
1053   /**
1054    * Return the button's default "icon" property.
1055    *
1056    * @return The current default icon
1057    */
1058   public Icon getIcon()
1059   {
1060     return default_icon;
1061   }
1062
1063   /**
1064    * Set the button's default "icon" property. This icon is used as a basis
1065    * for the pressed and disabled icons, if none are explicitly set.
1066    *
1067    * @param i The new default icon
1068    */
1069   public void setIcon(Icon i)
1070       {
1071     Icon old = default_icon;
1072     default_icon = i;
1073     if (old != i)
1074       {
1075         firePropertyChange(ICON_CHANGED_PROPERTY, old, i);
1076     revalidate();
1077     repaint();
1078   }
1079   }
1080
1081   /**
1082    * Return the button's "text" property. This property is synonymous with
1083    * the "label" property.
1084    *
1085    * @return The current "text" property
1086    */
1087   public String getText()
1088   {
1089     return text;
1090   }
1091
1092   /**
1093    * Set the button's "label" property. This property is synonymous with the
1094    * "text" property.
1095    *
1096    * @param label The new "label" property
1097    */
1098   public void setLabel(String label)
1099   {
1100     setText(label);
1101   }
1102
1103   /**
1104    * Return the button's "label" property. This property is synonymous with
1105    * the "text" property.
1106    *
1107    * @return The current "label" property
1108    */
1109   public String getLabel()
1110   {
1111     return getText();
1112   }
1113
1114   /**
1115    * Set the button's "text" property. This property is synonymous with the
1116    * "label" property.
1117    *
1118    * @param t The new "text" property
1119    */
1120   public void setText(String t)
1121   {
1122     String old = text;
1123     text = t;
1124     if (t != old)
1125       {
1126         firePropertyChange(TEXT_CHANGED_PROPERTY, old, t);
1127     revalidate();
1128     repaint();
1129   }
1130   }
1131
1132   /**
1133    * Return the button's "margin" property, which is an {@link Insets} object
1134    * describing the distance between the button's border and its text and
1135    * icon.
1136    *
1137    * @return The current "margin" property
1138    */
1139   public        Insets getMargin()
1140   {
1141     return margin;
1142   }
1143
1144   /**
1145    * Set the button's "margin" property, which is an {@link Insets} object
1146    * describing the distance between the button's border and its text and
1147    * icon.
1148    *
1149    * @param m The new "margin" property
1150    */
1151   public void setMargin(Insets m)
1152   {
1153     Insets old = margin;
1154     margin = m;
1155     if (m != old)
1156       {
1157         firePropertyChange(MARGIN_CHANGED_PROPERTY, old, m);
1158         revalidate();
1159     repaint();
1160   }
1161   }
1162
1163   /**
1164    * Return the button's "pressedIcon" property. The look and feel class
1165    * should paint this icon when the "pressed" property of the button's
1166    * {@link ButtonModel} is <code>true</code>. This property may be
1167    * <code>null</code>, in which case the default icon is used.
1168    *
1169    * @return The current "pressedIcon" property
1170    */
1171   public Icon getPressedIcon()
1172   {
1173     return pressed_icon;
1174   }
1175
1176   /**
1177    * Set the button's "pressedIcon" property. The look and feel class
1178    * should paint this icon when the "pressed" property of the button's
1179    * {@link ButtonModel} is <code>true</code>. This property may be
1180    * <code>null</code>, in which case the default icon is used.
1181    *
1182    * @param pressedIcon The new "pressedIcon" property
1183    */
1184   public void setPressedIcon(Icon pressedIcon)
1185   {
1186     Icon old = pressed_icon;
1187     pressed_icon = pressedIcon;
1188     if (pressed_icon != old)
1189       {
1190         firePropertyChange(PRESSED_ICON_CHANGED_PROPERTY, old, pressed_icon);
1191     revalidate();
1192     repaint();
1193   }
1194   }
1195
1196   /**
1197    * Return the button's "disabledIcon" property. The look and feel class
1198    * should paint this icon when the "enabled" property of the button's
1199    * {@link ButtonModel} is <code>false</code>. This property may be
1200    * <code>null</code>, in which case an icon is constructed, based on the
1201    * default icon.
1202    *
1203    * @return The current "disabledIcon" property
1204    */
1205   public Icon getDisabledIcon()
1206   {
1207     return disabled_icon;
1208   }
1209
1210   /**
1211    * Set the button's "disabledIcon" property. The look and feel class should
1212    * paint this icon when the "enabled" property of the button's {@link
1213    * ButtonModel} is <code>false</code>. This property may be
1214    * <code>null</code>, in which case an icon is constructed, based on the
1215    * default icon.
1216    *
1217    * @param disabledIcon The new "disabledIcon" property
1218    */
1219   public void setDisabledIcon(Icon disabledIcon)
1220   {
1221     disabled_icon = disabledIcon;
1222     revalidate();
1223     repaint();
1224   }
1225
1226   /**
1227    * Return the button's "paintFocus" property. This property controls
1228    * whether or not the look and feel class will paint a special indicator
1229    * of focus state for the button. If it is false, the button still paints
1230    * when focused, but no special decoration is painted to indicate the
1231    * presence of focus.
1232    *
1233    * @return The current "paintFocus" property
1234    */
1235   public boolean isFocusPainted()
1236   {
1237     return paint_focus;
1238   }
1239
1240   /**
1241    * Set the button's "paintFocus" property. This property controls whether
1242    * or not the look and feel class will paint a special indicator of focus
1243    * state for the button. If it is false, the button still paints when
1244    * focused, but no special decoration is painted to indicate the presence
1245    * of focus.
1246    *
1247    * @param b The new "paintFocus" property
1248    */
1249   public void setFocusPainted(boolean b)
1250   {
1251     boolean old = paint_focus;
1252     paint_focus = b;
1253
1254     if (old != b)
1255       {
1256         firePropertyChange(FOCUS_PAINTED_CHANGED_PROPERTY, old, b);
1257         revalidate();
1258         repaint();
1259       }
1260   }
1261
1262   /**
1263    * Return the button's "focusTraversable" property. This property controls
1264    * whether or not the button can receive focus when the user attempts to
1265    * traverse the focus hierarchy.
1266    *
1267    * @return The current "focusTraversable" property
1268    */
1269   public boolean isFocusTraversable()
1270   {
1271     return true;
1272   }
1273
1274   /**
1275    * Verifies that a particular key is one of the valid constants used for
1276    * describing horizontal alignment and positioning. The valid constants
1277    * are the following members of {@link SwingConstants}:
1278    * <code>RIGHT</code>, <code>LEFT</code>, <code>CENTER</code>,
1279    * <code>LEADING</code> or <code>TRAILING</code>.
1280    *
1281    * @param key The key to check
1282    * @param exception A message to include in an IllegalArgumentException
1283    *
1284    * @return the value of key
1285    *
1286    * @throws IllegalArgumentException If key is not one of the valid constants
1287    *
1288    * @see setHorizontalTextPosition()
1289    * @see setHorizontalAlignment()
1290    */
1291   protected  int checkHorizontalKey(int key, String exception)
1292   {
1293     switch (key)
1294       {
1295       case SwingConstants.RIGHT:
1296       case SwingConstants.LEFT:
1297       case SwingConstants.CENTER:
1298       case SwingConstants.LEADING:
1299       case SwingConstants.TRAILING:
1300         break;
1301       default:
1302         throw new IllegalArgumentException(exception);
1303       }
1304     return key;
1305   }
1306
1307   /**
1308    * Verifies that a particular key is one of the valid constants used for
1309    * describing vertical alignment and positioning. The valid constants are
1310    * the following members of {@link SwingConstants}: <code>TOP</code>,
1311    * <code>BOTTOM</code> or <code>CENTER</code>.
1312    *
1313    * @param key The key to check
1314    * @param exception A message to include in an IllegalArgumentException
1315    *
1316    * @return the value of key
1317    *
1318    * @throws IllegalArgumentException If key is not one of the valid constants
1319    *
1320    * @see setVerticalTextPosition()
1321    * @see setVerticalAlignment()
1322    */
1323   protected  int checkVerticalKey(int key, String exception)
1324   {
1325     switch (key)
1326       {
1327       case SwingConstants.TOP:
1328       case SwingConstants.BOTTOM:
1329       case SwingConstants.CENTER:
1330         break;
1331       default:
1332         throw new IllegalArgumentException(exception);
1333       }
1334     return key;
1335   }
1336
1337   /**
1338    * Configure various properties of the button by reading properties
1339    * of an {@link Action}. The mapping of properties is as follows:
1340    *
1341    * <table>
1342    *
1343    * <tr><th>Action keyed property</th> <th>AbstractButton property</th></tr>
1344    *
1345    * <tr><td>NAME                 </td> <td>text                   </td></tr>
1346    * <tr><td>SMALL_ICON           </td> <td>icon                   </td></tr>
1347    * <tr><td>SHORT_DESCRIPTION    </td> <td>toolTipText            </td></tr>
1348    * <tr><td>MNEMONIC_KEY         </td> <td>mnemonic               </td></tr>
1349    * <tr><td>ACTION_COMMAND_KEY   </td> <td>actionCommand          </td></tr>
1350    *
1351    * </table>
1352    *
1353    * <p>In addition, this method always sets the button's "enabled" property to
1354    * the value of the Action's "enabled" property.</p>
1355    *
1356    * <p>If the provided Action is <code>null</code>, the text, icon, and
1357    * toolTipText properties of the button are set to <code>null</code>, and
1358    * the "enabled" property is set to <code>true</code>; the mnemonic and
1359    * actionCommand properties are unchanged.</p>
1360    *
1361    * @param a An Action to configure the button from
1362    */
1363   protected  void configurePropertiesFromAction(Action a)
1364   {
1365     if (a == null)
1366       {
1367         setText(null);
1368         setIcon(null);
1369         setEnabled(true);
1370         setToolTipText(null);
1371       }
1372     else
1373       {
1374         setText((String)(a.getValue(Action.NAME)));
1375         setIcon((Icon)(a.getValue(Action.SMALL_ICON)));
1376         setEnabled(a.isEnabled());
1377         setToolTipText((String)(a.getValue(Action.SHORT_DESCRIPTION)));
1378         setMnemonic(((Integer)(a.getValue(Action.MNEMONIC_KEY))).intValue());
1379         setActionCommand((String)(a.getValue(Action.ACTION_COMMAND_KEY)));
1380       }
1381   }
1382
1383   /**
1384    * <p>A factory method which should return an {@link ActionListener} that
1385    * propagates events from the button's {@link ButtonModel} to any of the
1386    * button's ActionListeners. By default, this is an inner class which
1387    * calls {@link AbstractButton.fireActionPerformed} with a modified copy
1388    * of the incoming model {@link ActionEvent}.</p>
1389    *
1390    * <p>The button calls this method during construction, stores the
1391    * resulting ActionListener in its <code>actionListener</code> member
1392    * field, and subscribes it to the button's model. If the button's model
1393    * is changed, this listener is unsubscribed from the old model and
1394    * subscribed to the new one.</p>
1395    *
1396    * @return A new ActionListener 
1397    */
1398   protected  ActionListener createActionListener()
1399   {
1400     return new ActionListener()
1401       {
1402         public void actionPerformed(ActionEvent e)
1403         {
1404           e.setSource(AbstractButton.this);
1405           AbstractButton.this.fireActionPerformed(e);
1406         }
1407       };
1408   }
1409
1410   /**
1411    * <p>A factory method which should return a {@link PropertyChangeListener}
1412    * that accepts changes to the specified {@link Action} and reconfigure
1413    * the {@link AbstractButton}, by default using the {@link
1414    * configurePropertiesFromAction} method.</p>
1415    *
1416    * <p>The button calls this method whenever a new Action is assigned to
1417    * the button's "action" property, via {@link setAction}, and stores the
1418    * resulting PropertyChangeListener in its
1419    * <code>actionPropertyChangeListener</code> member field. The button
1420    * then subscribes the listener to the button's new action. If the
1421    * button's action is changed subsequently, the listener is unsubscribed
1422    * from the old action and subscribed to the new one.</p>
1423    *
1424    * @param a The Action which will be listened to, and which should be 
1425    * the same as the source of any PropertyChangeEvents received by the
1426    * new listener returned from this method.
1427    *
1428    * @return A new PropertyChangeListener
1429    */
1430   protected  PropertyChangeListener createActionPropertyChangeListener(Action a)
1431   {
1432     return new PropertyChangeListener()
1433       {
1434         public void propertyChange(PropertyChangeEvent e)
1435         {
1436           Action act = (Action)(e.getSource());
1437           AbstractButton.this.configurePropertiesFromAction(act);
1438         }
1439       };
1440   }
1441
1442   /**
1443    * <p>Factory method which creates a {@link ChangeListener}, used to
1444    * subscribe to ChangeEvents from the button's model. Subclasses of
1445    * AbstractButton may wish to override the listener used to subscribe to
1446    * such ChangeEvents. By default, the listener just propagates the
1447    * {@link ChangeEvent} to the button's ChangeListeners, via the {@link
1448    * AbstractButton.fireStateChanged} method.</p>
1449    *
1450    * <p>The button calls this method during construction, stores the
1451    * resulting ChangeListener in its <code>changeListener</code> member
1452    * field, and subscribes it to the button's model. If the button's model
1453    * is changed, this listener is unsubscribed from the old model and
1454    * subscribed to the new one.</p>
1455    *
1456    * @return The new ChangeListener
1457    */
1458   protected  ChangeListener createChangeListener()
1459   {
1460     return new ChangeListener()
1461       {
1462         public void stateChanged(ChangeEvent e)
1463         {
1464           AbstractButton.this.fireStateChanged(e);
1465           AbstractButton.this.revalidate();
1466           AbstractButton.this.repaint();          
1467         }
1468       };
1469   }
1470
1471   /**
1472    * <p>Factory method which creates a {@link ItemListener}, used to
1473    * subscribe to ItemEvents from the button's model. Subclasses of
1474    * AbstractButton may wish to override the listener used to subscribe to
1475    * such ItemEvents. By default, the listener just propagates the
1476    * {@link ItemEvent} to the button's ItemListeners, via the {@link
1477    * AbstractButton.fireItemStateChanged} method.</p>
1478    *
1479    * <p>The button calls this method during construction, stores the
1480    * resulting ItemListener in its <code>changeListener</code> member
1481    * field, and subscribes it to the button's model. If the button's model
1482    * is changed, this listener is unsubscribed from the old model and
1483    * subscribed to the new one.</p>
1484    *
1485    * <p>Note that ItemEvents are only generated from the button's model
1486    * when the model's <em>selected</em> property changes. If you want to
1487    * subscribe to other properties of the model, you must subscribe to
1488    * ChangeEvents.
1489    *
1490    * @return The new ItemListener
1491    */
1492   protected  ItemListener createItemListener()
1493   {
1494     return new ItemListener()
1495       {
1496         public void itemStateChanged(ItemEvent e)
1497         {
1498           AbstractButton.this.fireItemStateChanged(e);
1499         }
1500       };
1501   }
1502
1503   /**
1504    * Programmatically perform a "click" on the button: arming, pressing,
1505    * waiting, un-pressing, and disarming the model.
1506    */
1507   public void doClick()
1508   {
1509     doClick(100);
1510   }
1511
1512   /**
1513    * Programmatically perform a "click" on the button: arming, pressing,
1514    * waiting, un-pressing, and disarming the model.
1515    *
1516    * @param pressTime The number of milliseconds to wait in the pressed state
1517    */
1518   public void doClick(int pressTime)
1519   {
1520     getModel().setArmed(true);
1521     getModel().setPressed(true);
1522     try
1523   {
1524         java.lang.Thread.sleep(pressTime);
1525   }
1526     catch (java.lang.InterruptedException e)
1527   {
1528         // probably harmless
1529   }
1530     getModel().setPressed(false);
1531     getModel().setArmed(false);
1532   }
1533
1534   /**
1535    * Return the button's disabled selected icon. The look and feel class
1536    * should paint this icon when the "enabled" property of the button's model
1537    * is <code>false</code> and its "selected" property is
1538    * <code>true</code>. This icon can be <code>null</code>, in which case
1539    * it is synthesized from the button's selected icon.
1540    *
1541    * @return The current disabled selected icon
1542    */
1543   public Icon getDisabledSelectedIcon()
1544   {
1545     return disabled_selected_icon;
1546   }
1547
1548   /**
1549    * Set the button's disabled selected icon. The look and feel class
1550    * should paint this icon when the "enabled" property of the button's model
1551    * is <code>false</code> and its "selected" property is
1552    * <code>true</code>. This icon can be <code>null</code>, in which case
1553    * it is synthesized from the button's selected icon.
1554    *
1555    * @param disabledSelectedIcon The new disabled selected icon
1556    */
1557   public void setDisabledSelectedIcon(Icon disabledSelectedIcon)
1558   {
1559     Icon old = disabled_selected_icon;
1560     disabled_selected_icon = disabledSelectedIcon;
1561     if (old != disabledSelectedIcon)
1562   {
1563         firePropertyChange(DISABLED_SELECTED_ICON_CHANGED_PROPERTY, old, 
1564                            disabledSelectedIcon);
1565         revalidate();
1566         repaint();        
1567   }
1568   }
1569
1570
1571   /**
1572    * Return the button's rollover icon. The look and feel class should
1573    * paint this icon when the "rolloverEnabled" property of the button is
1574    * <code>true</code> and the mouse rolls over the button.
1575    *
1576    * @return The current rollover icon
1577    */
1578   public Icon getRolloverIcon()
1579   {
1580     return rollover_icon;
1581   }
1582
1583   /**
1584    * Set the button's rollover icon. The look and feel class should
1585    * paint this icon when the "rolloverEnabled" property of the button is
1586    * <code>true</code> and the mouse rolls over the button.
1587    *
1588    * @param rolloverIcon The new rollover icon
1589    */
1590   public void setRolloverIcon(Icon rolloverIcon)
1591   {
1592     Icon old = rollover_icon;
1593     rollover_icon = rolloverIcon;
1594     if (old != rolloverIcon)
1595   {
1596         firePropertyChange(ROLLOVER_ICON_CHANGED_PROPERTY, old, 
1597                            rolloverIcon);
1598         revalidate();
1599         repaint();
1600       }
1601   }
1602
1603   /**
1604    * Return the button's rollover selected icon. The look and feel class
1605    * should paint this icon when the "rolloverEnabled" property of the button
1606    * is <code>true</code>, the "selected" property of the button's model is
1607    * <code>true</code>, and the mouse rolls over the button.
1608    *
1609    * @return The current rollover selected icon
1610    */
1611   public Icon getRolloverSelectedIcon()
1612   {
1613     return rollover_selected_icon;
1614   }
1615
1616   /**
1617    * Set the button's rollover selected icon. The look and feel class
1618    * should paint this icon when the "rolloverEnabled" property of the button
1619    * is <code>true</code>, the "selected" property of the button's model is
1620    * <code>true</code>, and the mouse rolls over the button.
1621    *
1622    * @param rolloverSelectedIcon The new rollover selected icon
1623    */
1624   public void setRolloverSelectedIcon(Icon rolloverSelectedIcon)
1625   {
1626     Icon old = rollover_selected_icon;
1627     rollover_selected_icon = rolloverSelectedIcon;
1628     if (old != rolloverSelectedIcon)
1629   {
1630         firePropertyChange(ROLLOVER_SELECTED_ICON_CHANGED_PROPERTY, old, 
1631                            rolloverSelectedIcon);
1632         revalidate();
1633         repaint();
1634   }
1635   }
1636
1637
1638   /**
1639    * Return the button's selected icon. The look and feel class should
1640    * paint this icon when the "selected" property of the button's model is
1641    * <code>true</code>, and either the "rolloverEnabled" property of the
1642    * button is <code>false</code> or the mouse is not currently rolled
1643    * over the button.
1644    *
1645    * @return The current selected icon
1646    */
1647   public Icon getSelectedIcon()
1648   {
1649     return selected_icon;
1650   }
1651
1652   /**
1653    * Set the button's selected icon. The look and feel class should
1654    * paint this icon when the "selected" property of the button's model is
1655    * <code>true</code>, and either the "rolloverEnabled" property of the
1656    * button is <code>false</code> or the mouse is not currently rolled
1657    * over the button.
1658    *
1659    * @param selectedIcon The new selected icon
1660    */
1661   public void setSelectedIcon(Icon selectedIcon)
1662   {
1663     Icon old = selected_icon;
1664     selected_icon = selectedIcon;
1665     if (old != selectedIcon)
1666     {
1667         firePropertyChange(SELECTED_ICON_CHANGED_PROPERTY, old, 
1668                            selectedIcon);
1669         revalidate();
1670         repaint();
1671     }
1672   }
1673
1674   /**
1675    * Returns an single-element array containing the "text" property of the
1676    * button if the "selected" property of the button's model is
1677    * <code>true</code>, otherwise returns <code>null</code>.
1678    *
1679    * @return The button's "selected object" array
1680    */
1681   public Object[] getSelectedObjects()
1682   {
1683     if (isSelected())
1684       {
1685         Object[] objs = new Object[1];
1686         objs[0] = getText();
1687         return objs;
1688   }
1689     else
1690   {
1691         return null;
1692       }
1693   }
1694
1695   /**
1696    * Called when image data becomes available for one of the button's icons.
1697    *
1698    * @param img The image being updated
1699    * @param infoflags One of the constant codes in {@link ImageObserver} used to describe
1700    * updated portions of an image.
1701    * @param x X coordinate of the region being updated
1702    * @param y Y coordinate of the region being updated
1703    * @param w Width of the region beign updated
1704    * @param h Height of the region being updated
1705    *
1706    * @return <code>true</code> if img is equal to the button's current
1707    * icon, otherwise <code>false</code>
1708    */
1709   public boolean imageUpdate(Image img, int infoflags, int x, int y, int w,
1710                              int h)
1711         {
1712     return current_icon == img;
1713         }
1714
1715   /**
1716    * Returns the value of the button's "contentAreaFilled" property. This
1717    * property indicates whether the area surrounding the text and icon of
1718    * the button should be filled by the look and feel class.  If this
1719    * property is <code>false</code>, the look and feel class should leave
1720    * the content area transparent.
1721    *
1722    * @return The current value of the "contentAreaFilled" property
1723    */
1724   public boolean isContentAreaFilled()
1725             {
1726     return content_area_filled;
1727             }
1728
1729   /**
1730    * Sets the value of the button's "contentAreaFilled" property. This
1731    * property indicates whether the area surrounding the text and icon of
1732    * the button should be filled by the look and feel class.  If this
1733    * property is <code>false</code>, the look and feel class should leave
1734    * the content area transparent.
1735    *
1736    * @param b The new value of the "contentAreaFilled" property
1737    */
1738   public void setContentAreaFilled(boolean b)
1739             {
1740     boolean old = content_area_filled;
1741     content_area_filled = b;
1742     if (b != old)
1743       {
1744         firePropertyChange(CONTENT_AREA_FILLED_CHANGED_PROPERTY, old, b);
1745         revalidate();
1746               repaint();
1747             }
1748         }
1749
1750   /**
1751    * Paints the button's border, if the button's "borderPainted" property is
1752    * <code>true</code>, by out calling to the button's look and feel class.
1753    *
1754    * @param g The graphics context used to paint the border
1755    */
1756   protected void paintBorder(Graphics g)
1757             {
1758     if (isBorderPainted())
1759       super.paintBorder(g);
1760             }
1761
1762   /**
1763    * Returns a string, used only for debugging, which identifies or somehow
1764    * represents this button. The exact value is implementation-defined.
1765    *
1766    * @return A string representation of the button
1767    */
1768   protected String paramString()
1769   {
1770     return "AbstractButton";
1771   }
1772
1773
1774   /**
1775    * Set the "UI" property of the button, which is a look and feel class
1776    * responsible for handling the button's input events and painting it.
1777    *
1778    * @param ui The new "UI" property
1779    */
1780   public void setUI(ButtonUI ui)
1781         {
1782     super.setUI(ui);
1783         }
1784   
1785   /**
1786    * Set the "UI" property of the button, which is a look and feel class
1787    * responsible for handling the button's input events and painting it.
1788    *
1789    * @return The current "UI" property
1790    */
1791   public ButtonUI getUI()
1792   {
1793     return (ButtonUI) ui;
1794       }
1795   
1796   /**
1797    * Set the "UI" property to a class constructed, via the {@link
1798    * UIManager}, from the current look and feel. This should be overridden
1799    * for each subclass of AbstractButton, to retrieve a suitable {@link
1800    * ButtonUI} look and feel class.
1801    */
1802   public void updateUI()
1803   {
1804   }
1805 }