KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > swing > AbstractButton


1 /*
2  * @(#)AbstractButton.java 1.175 05/08/23
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7 package javax.swing;
8
9 import java.awt.*;
10 import java.awt.event.*;
11 import java.awt.image.*;
12 import java.text.*;
13 import java.awt.geom.*;
14 import java.beans.*;
15 import java.util.Enumeration JavaDoc;
16 import java.util.Vector JavaDoc;
17 import java.io.Serializable JavaDoc;
18 import javax.swing.event.*;
19 import javax.swing.border.*;
20 import javax.swing.plaf.*;
21 import javax.accessibility.*;
22 import javax.swing.text.*;
23 import javax.swing.text.html.*;
24 import javax.swing.plaf.basic.*;
25 import java.util.*;
26
27 /**
28  * Defines common behaviors for buttons and menu items.
29  * For further information see
30  * <a
31  href="http://java.sun.com/docs/books/tutorial/uiswing/components/button.html">How to Use Buttons, Check Boxes, and Radio Buttons</a>,
32  * a section in <em>The Java Tutorial</em>.
33  *
34  * <p>
35  *
36  * <strong>Warning:</strong>
37  * Serialized objects of this class will not be compatible with
38  * future Swing releases. The current serialization support is
39  * appropriate for short term storage or RMI between applications running
40  * the same version of Swing. As of 1.4, support for long term storage
41  * of all JavaBeans<sup><font size="-2">TM</font></sup>
42  * has been added to the <code>java.beans</code> package.
43  * Please see {@link java.beans.XMLEncoder}.
44  *
45  * @version 1.175 08/23/05
46  * @author Jeff Dinkins
47  */

48 public abstract class AbstractButton extends JComponent JavaDoc implements ItemSelectable, SwingConstants JavaDoc {
49
50     // *********************************
51
// ******* Button properties *******
52
// *********************************
53

54     /** Identifies a change in the button model. */
55     public static final String JavaDoc MODEL_CHANGED_PROPERTY = "model";
56     /** Identifies a change in the button's text. */
57     public static final String JavaDoc TEXT_CHANGED_PROPERTY = "text";
58     /** Identifies a change to the button's mnemonic. */
59     public static final String JavaDoc MNEMONIC_CHANGED_PROPERTY = "mnemonic";
60
61     // Text positioning and alignment
62
/** Identifies a change in the button's margins. */
63     public static final String JavaDoc MARGIN_CHANGED_PROPERTY = "margin";
64     /** Identifies a change in the button's vertical alignment. */
65     public static final String JavaDoc VERTICAL_ALIGNMENT_CHANGED_PROPERTY = "verticalAlignment";
66     /** Identifies a change in the button's horizontal alignment. */
67     public static final String JavaDoc HORIZONTAL_ALIGNMENT_CHANGED_PROPERTY = "horizontalAlignment";
68
69     /** Identifies a change in the button's vertical text position. */
70     public static final String JavaDoc VERTICAL_TEXT_POSITION_CHANGED_PROPERTY = "verticalTextPosition";
71     /** Identifies a change in the button's horizontal text position. */
72     public static final String JavaDoc HORIZONTAL_TEXT_POSITION_CHANGED_PROPERTY = "horizontalTextPosition";
73
74     // Paint options
75
/**
76      * Identifies a change to having the border drawn,
77      * or having it not drawn.
78      */

79     public static final String JavaDoc BORDER_PAINTED_CHANGED_PROPERTY = "borderPainted";
80     /**
81      * Identifies a change to having the border highlighted when focused,
82      * or not.
83      */

84     public static final String JavaDoc FOCUS_PAINTED_CHANGED_PROPERTY = "focusPainted";
85     /**
86      * Identifies a change from rollover enabled to disabled or back
87      * to enabled.
88      */

89     public static final String JavaDoc ROLLOVER_ENABLED_CHANGED_PROPERTY = "rolloverEnabled";
90     /**
91      * Identifies a change to having the button paint the content area.
92      */

93     public static final String JavaDoc CONTENT_AREA_FILLED_CHANGED_PROPERTY = "contentAreaFilled";
94
95     // Icons
96
/** Identifies a change to the icon that represents the button. */
97     public static final String JavaDoc ICON_CHANGED_PROPERTY = "icon";
98
99     /**
100      * Identifies a change to the icon used when the button has been
101      * pressed.
102      */

103     public static final String JavaDoc PRESSED_ICON_CHANGED_PROPERTY = "pressedIcon";
104     /**
105      * Identifies a change to the icon used when the button has
106      * been selected.
107      */

108     public static final String JavaDoc SELECTED_ICON_CHANGED_PROPERTY = "selectedIcon";
109
110     /**
111      * Identifies a change to the icon used when the cursor is over
112      * the button.
113      */

114     public static final String JavaDoc ROLLOVER_ICON_CHANGED_PROPERTY = "rolloverIcon";
115     /**
116      * Identifies a change to the icon used when the cursor is
117      * over the button and it has been selected.
118      */

119     public static final String JavaDoc ROLLOVER_SELECTED_ICON_CHANGED_PROPERTY = "rolloverSelectedIcon";
120
121     /**
122      * Identifies a change to the icon used when the button has
123      * been disabled.
124      */

125     public static final String JavaDoc DISABLED_ICON_CHANGED_PROPERTY = "disabledIcon";
126     /**
127      * Identifies a change to the icon used when the button has been
128      * disabled and selected.
129      */

130     public static final String JavaDoc DISABLED_SELECTED_ICON_CHANGED_PROPERTY = "disabledSelectedIcon";
131
132
133     /** The data model that determines the button's state. */
134     protected ButtonModel JavaDoc model = null;
135
136     private String JavaDoc text = ""; // for BeanBox
137
private Insets margin = null;
138     private Insets defaultMargin = null;
139
140     // Button icons
141
// PENDING(jeff) - hold icons in an array
142
private Icon JavaDoc defaultIcon = null;
143     private Icon JavaDoc pressedIcon = null;
144     private Icon JavaDoc disabledIcon = null;
145
146     private Icon JavaDoc selectedIcon = null;
147     private Icon JavaDoc disabledSelectedIcon = null;
148
149     private Icon JavaDoc rolloverIcon = null;
150     private Icon JavaDoc rolloverSelectedIcon = null;
151     
152     // Display properties
153
private boolean paintBorder = true;
154     private boolean paintFocus = true;
155     private boolean rolloverEnabled = false;
156     private boolean contentAreaFilled = true;
157
158     // Icon/Label Alignment
159
private int verticalAlignment = CENTER;
160     private int horizontalAlignment = CENTER;
161     
162     private int verticalTextPosition = CENTER;
163     private int horizontalTextPosition = TRAILING;
164
165     private int iconTextGap = 4;
166
167     private int mnemonic;
168     private int mnemonicIndex = -1;
169
170     private long multiClickThreshhold = 0;
171
172     private boolean borderPaintedSet = false;
173     private boolean rolloverEnabledSet = false;
174     private boolean iconTextGapSet = false;
175     private boolean contentAreaFilledSet = false;
176
177     // Whether or not we've set the LayoutManager.
178
private boolean setLayout = false;
179
180     // This is only used by JButton, promoted to avoid an extra
181
// boolean field in JButton
182
boolean defaultCapable = true;
183
184     /**
185      * Combined listeners: ActionListener, ChangeListener, ItemListener.
186      */

187     private Handler handler;
188     
189     /**
190      * The button model's <code>changeListener</code>.
191      */

192     protected ChangeListener changeListener = null;
193     /**
194      * The button model's <code>ActionListener</code>.
195      */

196     protected ActionListener actionListener = null;
197     /**
198      * The button model's <code>ItemListener</code>.
199      */

200     protected ItemListener itemListener = null;
201
202     /**
203      * Only one <code>ChangeEvent</code> is needed per button
204      * instance since the
205      * event's only state is the source property. The source of events
206      * generated is always "this".
207      */

208     protected transient ChangeEvent changeEvent;
209     
210     /**
211      * Returns the button's text.
212      * @return the buttons text
213      * @see #setText
214      */

215     public String JavaDoc getText() {
216         return text;
217     }
218     
219     /**
220      * Sets the button's text.
221      * @param text the string used to set the text
222      * @see #getText
223      * @beaninfo
224      * bound: true
225      * preferred: true
226      * attribute: visualUpdate true
227      * description: The button's text.
228      */

229     public void setText(String JavaDoc text) {
230         String JavaDoc oldValue = this.text;
231         this.text = text;
232         firePropertyChange(TEXT_CHANGED_PROPERTY, oldValue, text);
233         updateDisplayedMnemonicIndex(text, getMnemonic());
234
235         if (accessibleContext != null) {
236             accessibleContext.firePropertyChange(
237                 AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
238                 oldValue, text);
239         }
240         if (text == null || oldValue == null || !text.equals(oldValue)) {
241             revalidate();
242             repaint();
243         }
244     }
245
246
247     /**
248      * Returns the state of the button. True if the
249      * toggle button is selected, false if it's not.
250      * @return true if the toggle button is selected, otherwise false
251      */

252     public boolean isSelected() {
253         return model.isSelected();
254     }
255  
256     /**
257      * Sets the state of the button. Note that this method does not
258      * trigger an <code>actionEvent</code>.
259      * Call <code>doClick</code> to perform a programatic action change.
260      *
261      * @param b true if the button is selected, otherwise false
262      */

263     public void setSelected(boolean b) {
264         boolean oldValue = isSelected();
265
266         // TIGER - 4840653
267
// Removed code which fired an AccessibleState.SELECTED
268
// PropertyChangeEvent since this resulted in two
269
// identical events being fired since
270
// AbstractButton.fireItemStateChanged also fires the
271
// same event. This caused screen readers to speak the
272
// name of the item twice.
273

274         model.setSelected(b);
275     }
276
277     /**
278      * Programmatically perform a "click". This does the same
279      * thing as if the user had pressed and released the button.
280      */

281     public void doClick() {
282         doClick(68);
283     }
284
285     /**
286      * Programmatically perform a "click". This does the same
287      * thing as if the user had pressed and released the button.
288      * The button stays visually "pressed" for <code>pressTime</code>
289      * milliseconds.
290      *
291      * @param pressTime the time to "hold down" the button, in milliseconds
292      */

293     public void doClick(int pressTime) {
294         Dimension size = getSize();
295         model.setArmed(true);
296         model.setPressed(true);
297         paintImmediately(new Rectangle(0,0, size.width, size.height));
298         try {
299             Thread.currentThread().sleep(pressTime);
300         } catch(InterruptedException JavaDoc ie) {
301         }
302         model.setPressed(false);
303         model.setArmed(false);
304     }
305
306     /**
307      * Sets space for margin between the button's border and
308      * the label. Setting to <code>null</code> will cause the button to
309      * use the default margin. The button's default <code>Border</code>
310      * object will use this value to create the proper margin.
311      * However, if a non-default border is set on the button,
312      * it is that <code>Border</code> object's responsibility to create the
313      * appropriate margin space (else this property will
314      * effectively be ignored).
315      *
316      * @param m the space between the border and the label
317      *
318      * @beaninfo
319      * bound: true
320      * attribute: visualUpdate true
321      * description: The space between the button's border and the label.
322      */

323     public void setMargin(Insets m) {
324         // Cache the old margin if it comes from the UI
325
if(m instanceof UIResource) {
326             defaultMargin = m;
327         } else if(margin instanceof UIResource) {
328             defaultMargin = margin;
329         }
330             
331         // If the client passes in a null insets, restore the margin
332
// from the UI if possible
333
if(m == null && defaultMargin != null) {
334             m = defaultMargin;
335         }
336
337         Insets old = margin;
338         margin = m;
339         firePropertyChange(MARGIN_CHANGED_PROPERTY, old, m);
340         if (old == null || !old.equals(m)) {
341             revalidate();
342             repaint();
343         }
344     }
345
346     /**
347      * Returns the margin between the button's border and
348      * the label.
349      *
350      * @return an <code>Insets</code> object specifying the margin
351      * between the botton's border and the label
352      * @see #setMargin
353      */

354     public Insets getMargin() {
355         return (margin == null) ? null : (Insets) margin.clone();
356     }
357
358     /**
359      * Returns the default icon.
360      * @return the default <code>Icon</code>
361      * @see #setIcon
362      */

363     public Icon JavaDoc getIcon() {
364         return defaultIcon;
365     }
366     
367     /**
368      * Sets the button's default icon. This icon is
369      * also used as the "pressed" and "disabled" icon if
370      * there is no explicitly set pressed icon.
371      *
372      * @param defaultIcon the icon used as the default image
373      * @see #getIcon
374      * @see #setPressedIcon
375      * @beaninfo
376      * bound: true
377      * attribute: visualUpdate true
378      * description: The button's default icon
379      */

380     public void setIcon(Icon JavaDoc defaultIcon) {
381         Icon JavaDoc oldValue = this.defaultIcon;
382         this.defaultIcon = defaultIcon;
383
384         /* If the default icon has really changed and we had
385          * generated the disabled icon for this component,
386          * (i.e. setDisabledIcon() was never called) then
387          * clear the disabledIcon field.
388          */

389         if (defaultIcon != oldValue && (disabledIcon instanceof UIResource)) {
390             disabledIcon = null;
391         }
392
393         firePropertyChange(ICON_CHANGED_PROPERTY, oldValue, defaultIcon);
394         if (accessibleContext != null) {
395             accessibleContext.firePropertyChange(
396                 AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
397                 oldValue, defaultIcon);
398         }
399         if (defaultIcon != oldValue) {
400             if (defaultIcon == null || oldValue == null ||
401                 defaultIcon.getIconWidth() != oldValue.getIconWidth() ||
402                 defaultIcon.getIconHeight() != oldValue.getIconHeight()) {
403                 revalidate();
404             }
405             repaint();
406         }
407     }
408     
409     /**
410      * Returns the pressed icon for the button.
411      * @return the <code>pressedIcon</code> property
412      * @see #setPressedIcon
413      */

414     public Icon JavaDoc getPressedIcon() {
415         return pressedIcon;
416     }
417     
418     /**
419      * Sets the pressed icon for the button.
420      * @param pressedIcon the icon used as the "pressed" image
421      * @see #getPressedIcon
422      * @beaninfo
423      * bound: true
424      * attribute: visualUpdate true
425      * description: The pressed icon for the button.
426      */

427     public void setPressedIcon(Icon JavaDoc pressedIcon) {
428         Icon JavaDoc oldValue = this.pressedIcon;
429         this.pressedIcon = pressedIcon;
430         firePropertyChange(PRESSED_ICON_CHANGED_PROPERTY, oldValue, pressedIcon);
431         if (accessibleContext != null) {
432             accessibleContext.firePropertyChange(
433                 AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
434                 oldValue, pressedIcon);
435         }
436         if (pressedIcon != oldValue) {
437             if (getModel().isPressed()) {
438                 repaint();
439             }
440         }
441     }
442
443     /**
444      * Returns the selected icon for the button.
445      * @return the <code>selectedIcon</code> property
446      * @see #setSelectedIcon
447      */

448     public Icon JavaDoc getSelectedIcon() {
449         return selectedIcon;
450     }
451     
452     /**
453      * Sets the selected icon for the button.
454      * @param selectedIcon the icon used as the "selected" image
455      * @see #getSelectedIcon
456      * @beaninfo
457      * bound: true
458      * attribute: visualUpdate true
459      * description: The selected icon for the button.
460      */

461     public void setSelectedIcon(Icon JavaDoc selectedIcon) {
462         Icon JavaDoc oldValue = this.selectedIcon;
463         this.selectedIcon = selectedIcon;
464
465         /* If the default selected icon has really changed and we had
466          * generated the disabled selected icon for this component,
467          * (i.e. setDisabledSelectedIcon() was never called) then
468          * clear the disabledSelectedIcon field.
469          */

470         if (selectedIcon != oldValue &&
471             disabledSelectedIcon instanceof UIResource) {
472
473             disabledSelectedIcon = null;
474         }
475
476         firePropertyChange(SELECTED_ICON_CHANGED_PROPERTY, oldValue, selectedIcon);
477         if (accessibleContext != null) {
478             accessibleContext.firePropertyChange(
479                 AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
480                 oldValue, selectedIcon);
481         }
482         if (selectedIcon != oldValue) {
483             if (isSelected()) {
484                 repaint();
485             }
486         }
487     }
488
489     /**
490      * Returns the rollover icon for the button.
491      * @return the <code>rolloverIcon</code> property
492      * @see #setRolloverIcon
493      */

494     public Icon JavaDoc getRolloverIcon() {
495         return rolloverIcon;
496     }
497     
498     /**
499      * Sets the rollover icon for the button.
500      * @param rolloverIcon the icon used as the "rollover" image
501      * @see #getRolloverIcon
502      * @beaninfo
503      * bound: true
504      * attribute: visualUpdate true
505      * description: The rollover icon for the button.
506      */

507     public void setRolloverIcon(Icon JavaDoc rolloverIcon) {
508         Icon JavaDoc oldValue = this.rolloverIcon;
509         this.rolloverIcon = rolloverIcon;
510         firePropertyChange(ROLLOVER_ICON_CHANGED_PROPERTY, oldValue, rolloverIcon);
511         if (accessibleContext != null) {
512             accessibleContext.firePropertyChange(
513                 AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
514                 oldValue, rolloverIcon);
515         }
516         setRolloverEnabled(true);
517         if (rolloverIcon != oldValue) {
518             // No way to determine whether we are currently in
519
// a rollover state, so repaint regardless
520
repaint();
521         }
522       
523     }
524     
525     /**
526      * Returns the rollover selection icon for the button.
527      * @return the <code>rolloverSelectedIcon</code> property
528      * @see #setRolloverSelectedIcon
529      */

530     public Icon JavaDoc getRolloverSelectedIcon() {
531         return rolloverSelectedIcon;
532     }
533     
534     /**
535      * Sets the rollover selected icon for the button.
536      * @param rolloverSelectedIcon the icon used as the
537      * "selected rollover" image
538      * @see #getRolloverSelectedIcon
539      * @beaninfo
540      * bound: true
541      * attribute: visualUpdate true
542      * description: The rollover selected icon for the button.
543      */

544     public void setRolloverSelectedIcon(Icon JavaDoc rolloverSelectedIcon) {
545         Icon JavaDoc oldValue = this.rolloverSelectedIcon;
546         this.rolloverSelectedIcon = rolloverSelectedIcon;
547         firePropertyChange(ROLLOVER_SELECTED_ICON_CHANGED_PROPERTY, oldValue, rolloverSelectedIcon);
548         if (accessibleContext != null) {
549             accessibleContext.firePropertyChange(
550                 AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
551                 oldValue, rolloverSelectedIcon);
552         }
553         setRolloverEnabled(true);
554         if (rolloverSelectedIcon != oldValue) {
555             // No way to determine whether we are currently in
556
// a rollover state, so repaint regardless
557
if (isSelected()) {
558                 repaint();
559             }
560         }
561     }
562     
563     /**
564      * Returns the icon used by the button when it's disabled.
565      * If no disabled icon has been set this will forward the call to
566      * the look and feel to construct an appropriate disabled Icon.
567      * <p>
568      * Some look and feels might not render the disabled Icon, in which
569      * case they will ignore this.
570      *
571      * @return the <code>disabledIcon</code> property
572      * @see #getPressedIcon
573      * @see #setDisabledIcon
574      * @see javax.swing.LookAndFeel#getDisabledIcon
575      */

576     public Icon JavaDoc getDisabledIcon() {
577         if (disabledIcon == null) {
578             disabledIcon = UIManager.getLookAndFeel().getDisabledIcon(this, getIcon());
579             if (disabledIcon != null) {
580                 firePropertyChange(DISABLED_ICON_CHANGED_PROPERTY, null, disabledIcon);
581             }
582         }
583         return disabledIcon;
584     }
585     
586     /**
587      * Sets the disabled icon for the button.
588      * @param disabledIcon the icon used as the disabled image
589      * @see #getDisabledIcon
590      * @beaninfo
591      * bound: true
592      * attribute: visualUpdate true
593      * description: The disabled icon for the button.
594      */

595     public void setDisabledIcon(Icon JavaDoc disabledIcon) {
596         Icon JavaDoc oldValue = this.disabledIcon;
597         this.disabledIcon = disabledIcon;
598         firePropertyChange(DISABLED_ICON_CHANGED_PROPERTY, oldValue, disabledIcon);
599         if (accessibleContext != null) {
600             accessibleContext.firePropertyChange(
601                 AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
602                 oldValue, disabledIcon);
603         }
604         if (disabledIcon != oldValue) {
605             if (!isEnabled()) {
606                 repaint();
607             }
608         }
609     }
610     
611     /**
612      * Returns the icon used by the button when it's disabled and selected.
613      * If no disabled selection icon has been set, this will forward
614      * the call to the LookAndFeel to construct an appropriate disabled
615      * Icon from the selection icon if it has been set and to
616      * <code>getDisabledIcon()</code> otherwise.
617      * <p>
618      * Some look and feels might not render the disabled selected Icon, in
619      * which case they will ignore this.
620      *
621      * @return the <code>disabledSelectedIcon</code> property
622      * @see #getDisabledIcon
623      * @see #setDisabledSelectedIcon
624      * @see javax.swing.LookAndFeel#getDisabledSelectedIcon
625      */

626     public Icon JavaDoc getDisabledSelectedIcon() {
627         if (disabledSelectedIcon == null) {
628              if (selectedIcon != null) {
629                  disabledSelectedIcon = UIManager.getLookAndFeel().
630                          getDisabledSelectedIcon(this, getSelectedIcon());
631              } else {
632                  return getDisabledIcon();
633              }
634         }
635         return disabledSelectedIcon;
636     }
637
638     /**
639      * Sets the disabled selection icon for the button.
640      * @param disabledSelectedIcon the icon used as the disabled
641      * selection image
642      * @see #getDisabledSelectedIcon
643      * @beaninfo
644      * bound: true
645      * attribute: visualUpdate true
646      * description: The disabled selection icon for the button.
647      */

648     public void setDisabledSelectedIcon(Icon JavaDoc disabledSelectedIcon) {
649         Icon JavaDoc oldValue = this.disabledSelectedIcon;
650         this.disabledSelectedIcon = disabledSelectedIcon;
651         firePropertyChange(DISABLED_SELECTED_ICON_CHANGED_PROPERTY, oldValue, disabledSelectedIcon);
652         if (accessibleContext != null) {
653             accessibleContext.firePropertyChange(
654                 AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
655                 oldValue, disabledSelectedIcon);
656         }
657         if (disabledSelectedIcon != oldValue) {
658             if (disabledSelectedIcon == null || oldValue == null ||
659                 disabledSelectedIcon.getIconWidth() != oldValue.getIconWidth() ||
660                 disabledSelectedIcon.getIconHeight() != oldValue.getIconHeight()) {
661                 revalidate();
662             }
663             if (!isEnabled() && isSelected()) {
664                 repaint();
665             }
666         }
667     }
668
669     /**
670      * Returns the vertical alignment of the text and icon.
671      *
672      * @return the <code>verticalAlignment</code> property, one of the
673      * following values:
674      * <ul>
675      * <li>SwingConstants.CENTER (the default)
676      * <li>SwingConstants.TOP
677      * <li>SwingConstants.BOTTOM
678      * </ul>
679      */

680     public int getVerticalAlignment() {
681         return verticalAlignment;
682     }
683     
684     /**
685      * Sets the vertical alignment of the icon and text.
686      * @param alignment one of the following values:
687      * <ul>
688      * <li>SwingConstants.CENTER (the default)
689      * <li>SwingConstants.TOP
690      * <li>SwingConstants.BOTTOM
691      * </ul>
692      * @beaninfo
693      * bound: true
694      * enum: TOP SwingConstants.TOP
695      * CENTER SwingConstants.CENTER
696      * BOTTOM SwingConstants.BOTTOM
697      * attribute: visualUpdate true
698      * description: The vertical alignment of the icon and text.
699      */

700     public void setVerticalAlignment(int alignment) {
701         if (alignment == verticalAlignment) return;
702         int oldValue = verticalAlignment;
703         verticalAlignment = checkVerticalKey(alignment, "verticalAlignment");
704         firePropertyChange(VERTICAL_ALIGNMENT_CHANGED_PROPERTY, oldValue, verticalAlignment); repaint();
705     }
706     
707     /**
708      * Returns the horizontal alignment of the icon and text.
709      * @return the <code>horizontalAlignment</code> property,
710      * one of the following values:
711      * <ul>
712      * <li>SwingConstants.RIGHT (the default)
713      * <li>SwingConstants.LEFT
714      * <li>SwingConstants.CENTER
715      * <li>SwingConstants.LEADING
716      * <li>SwingConstants.TRAILING
717      * </ul>
718      */

719     public int getHorizontalAlignment() {
720         return horizontalAlignment;
721     }
722     
723     /**
724      * Sets the horizontal alignment of the icon and text.
725      * @param alignment one of the following values:
726      * <ul>
727      * <li>SwingConstants.RIGHT (the default)
728      * <li>SwingConstants.LEFT
729      * <li>SwingConstants.CENTER
730      * <li>SwingConstants.LEADING
731      * <li>SwingConstants.TRAILING
732      * </ul>
733      * @beaninfo
734      * bound: true
735      * enum: LEFT SwingConstants.LEFT
736      * CENTER SwingConstants.CENTER
737      * RIGHT SwingConstants.RIGHT
738      * LEADING SwingConstants.LEADING
739      * TRAILING SwingConstants.TRAILING
740      * attribute: visualUpdate true
741      * description: The horizontal alignment of the icon and text.
742      */

743     public void setHorizontalAlignment(int alignment) {
744         if (alignment == horizontalAlignment) return;
745         int oldValue = horizontalAlignment;
746         horizontalAlignment = checkHorizontalKey(alignment,
747                                                  "horizontalAlignment");
748         firePropertyChange(HORIZONTAL_ALIGNMENT_CHANGED_PROPERTY,
749                            oldValue, horizontalAlignment);
750         repaint();
751     }
752
753     
754     /**
755      * Returns the vertical position of the text relative to the icon.
756      * @return the <code>verticalTextPosition</code> property,
757      * one of the following values:
758      * <ul>
759      * <li>SwingConstants.CENTER (the default)
760      * <li>SwingConstants.TOP
761      * <li>SwingConstants.BOTTOM
762      * </ul>
763      */

764     public int getVerticalTextPosition() {
765         return verticalTextPosition;
766     }
767     
768     /**
769      * Sets the vertical position of the text relative to the icon.
770      * @param textPosition one of the following values:
771      * <ul>
772      * <li>SwingConstants.CENTER (the default)
773      * <li>SwingConstants.TOP
774      * <li>SwingConstants.BOTTOM
775      * </ul>
776      * @beaninfo
777      * bound: true
778      * enum: TOP SwingConstants.TOP
779      * CENTER SwingConstants.CENTER
780      * BOTTOM SwingConstants.BOTTOM
781      * attribute: visualUpdate true
782      * description: The vertical position of the text relative to the icon.
783      */

784     public void setVerticalTextPosition(int textPosition) {
785         if (textPosition == verticalTextPosition) return;
786         int oldValue = verticalTextPosition;
787         verticalTextPosition = checkVerticalKey(textPosition, "verticalTextPosition");
788         firePropertyChange(VERTICAL_TEXT_POSITION_CHANGED_PROPERTY, oldValue, verticalTextPosition);
789         repaint();
790     }
791     
792     /**
793      * Returns the horizontal position of the text relative to the icon.
794      * @return the <code>horizontalTextPosition</code> property,
795      * one of the following values:
796      * <ul>
797      * <li>SwingConstants.RIGHT
798      * <li>SwingConstants.LEFT
799      * <li>SwingConstants.CENTER
800      * <li>SwingConstants.LEADING
801      * <li>SwingConstants.TRAILING (the default)
802      * </ul>
803      */

804     public int getHorizontalTextPosition() {
805         return horizontalTextPosition;
806     }
807     
808     /**
809      * Sets the horizontal position of the text relative to the icon.
810      * @param textPosition one of the following values:
811      * <ul>
812      * <li>SwingConstants.RIGHT
813      * <li>SwingConstants.LEFT
814      * <li>SwingConstants.CENTER
815      * <li>SwingConstants.LEADING
816      * <li>SwingConstants.TRAILING (the default)
817      * </ul>
818      * @exception IllegalArgumentException if <code>textPosition</code>
819      * is not one of the legal values listed above
820      * @beaninfo
821      * bound: true
822      * enum: LEFT SwingConstants.LEFT
823      * CENTER SwingConstants.CENTER
824      * RIGHT SwingConstants.RIGHT
825      * LEADING SwingConstants.LEADING
826      * TRAILING SwingConstants.TRAILING
827      * attribute: visualUpdate true
828      * description: The horizontal position of the text relative to the icon.
829      */

830     public void setHorizontalTextPosition(int textPosition) {
831         if (textPosition == horizontalTextPosition) return;
832         int oldValue = horizontalTextPosition;
833         horizontalTextPosition = checkHorizontalKey(textPosition,
834                                                     "horizontalTextPosition");
835         firePropertyChange(HORIZONTAL_TEXT_POSITION_CHANGED_PROPERTY,
836                            oldValue,
837                            horizontalTextPosition);
838         repaint();
839     }
840     
841     /**
842      * Returns the amount of space between the text and the icon
843      * displayed in this button.
844      *
845      * @return an int equal to the number of pixels between the text
846      * and the icon.
847      * @since 1.4
848      * @see #setIconTextGap
849      */

850     public int getIconTextGap() {
851         return iconTextGap;
852     }
853
854     /**
855      * If both the icon and text properties are set, this property
856      * defines the space between them.
857      * <p>
858      * The default value of this property is 4 pixels.
859      * <p>
860      * This is a JavaBeans bound property.
861      *
862      * @since 1.4
863      * @see #getIconTextGap
864      * @beaninfo
865      * bound: true
866      * attribute: visualUpdate true
867      * description: If both the icon and text properties are set, this
868      * property defines the space between them.
869      */

870     public void setIconTextGap(int iconTextGap) {
871         int oldValue = this.iconTextGap;
872         this.iconTextGap = iconTextGap;
873     iconTextGapSet = true;
874         firePropertyChange("iconTextGap", oldValue, iconTextGap);
875         if (iconTextGap != oldValue) {
876             revalidate();
877             repaint();
878         }
879     }
880
881     /**
882      * Verify that key is a legal value for the
883      * <code>horizontalAlignment</code> properties.
884      *
885      * @param key the property value to check, one of the following values:
886      * <ul>
887      * <li>SwingConstants.RIGHT (the default)
888      * <li>SwingConstants.LEFT
889      * <li>SwingConstants.CENTER
890      * <li>SwingConstants.LEADING
891      * <li>SwingConstants.TRAILING
892      * </ul>
893      * @param exception the <code>IllegalArgumentException</code>
894      * detail message
895      * @exception IllegalArgumentException if key is not one of the legal
896      * values listed above
897      * @see #setHorizontalTextPosition
898      * @see #setHorizontalAlignment
899      */

900     protected int checkHorizontalKey(int key, String JavaDoc exception) {
901         if ((key == LEFT) ||
902             (key == CENTER) ||
903             (key == RIGHT) ||
904             (key == LEADING) ||
905             (key == TRAILING)) {
906             return key;
907         } else {
908             throw new IllegalArgumentException JavaDoc(exception);
909         }
910     }
911     
912     /**
913      * Ensures that the key is a valid. Throws an
914      * <code>IllegalArgumentException</code>
915      * exception otherwise.
916      *
917      * @param key the value to check, one of the following values:
918      * <ul>
919      * <li>SwingConstants.CENTER (the default)
920      * <li>SwingConstants.TOP
921      * <li>SwingConstants.BOTTOM
922      * </ul>
923      * @param exception a string to be passed to the
924      * <code>IllegalArgumentException</code> call if key
925      * is not one of the valid values listed above
926      * @exception IllegalArgumentException if key is not one of the legal
927      * values listed above
928      */

929     protected int checkVerticalKey(int key, String JavaDoc exception) {
930         if ((key == TOP) || (key == CENTER) || (key == BOTTOM)) {
931             return key;
932         } else {
933             throw new IllegalArgumentException JavaDoc(exception);
934         }
935     }
936     
937     /**
938      * Sets the action command for this button.
939      * @param actionCommand the action command for this button
940      */

941     public void setActionCommand(String JavaDoc actionCommand) {
942         getModel().setActionCommand(actionCommand);
943     }
944     
945     /**
946      * Returns the action command for this button.
947      * @return the action command for this button
948      */

949     public String JavaDoc getActionCommand() {
950         String JavaDoc ac = getModel().getActionCommand();
951         if(ac == null) {
952             ac = getText();
953         }
954         return ac;
955     }
956     
957     private Action JavaDoc action;
958     private PropertyChangeListener actionPropertyChangeListener;
959
960     /**
961      * Sets the <code>Action</code> for the <code>ActionEvent</code> source.
962      * The new <code>Action</code> replaces any previously set
963      * <code>Action</code> but does not affect <code>ActionListeners</code>
964      * independently added with <code>addActionListener</code>.
965      * If the <code>Action</code> is already a registered
966      * <code>ActionListener</code> for the button, it is not re-registered.
967      * <p>
968      * A side-effect of setting the <code>Action</code> is that the
969      * <code>ActionEvent</code> source's properties are immediately
970      * set from the values in the <code>Action</code> (performed by the
971      * method <code>configurePropertiesFromAction</code>) and
972      * subsequently updated as the <code>Action</code>'s properties change
973      * (via a <code>PropertyChangeListener</code> created by the method
974      * <code>createActionPropertyChangeListener</code>.
975      *
976      * @param a the <code>Action</code> for the <code>AbstractButton</code>,
977      * or <code>null</code>
978      * @since 1.3
979      * @see Action
980      * @see #getAction
981      * @see #configurePropertiesFromAction
982      * @see #createActionPropertyChangeListener
983      * @beaninfo
984      * bound: true
985      * attribute: visualUpdate true
986      * description: the Action instance connected with this ActionEvent source
987      */

988     public void setAction(Action JavaDoc a) {
989     Action JavaDoc oldValue = getAction();
990     if (action==null || !action.equals(a)) {
991         action = a;
992         if (oldValue!=null) {
993         removeActionListener(oldValue);
994         oldValue.removePropertyChangeListener(actionPropertyChangeListener);
995         actionPropertyChangeListener = null;
996         }
997         configurePropertiesFromAction(action);
998         if (action!=null) {
999         // Don't add if it is already a listener
1000
if (!isListener(ActionListener.class, action)) {
1001            addActionListener(action);
1002        }
1003        // Reverse linkage:
1004
actionPropertyChangeListener = createActionPropertyChangeListener(action);
1005        action.addPropertyChangeListener(actionPropertyChangeListener);
1006        }
1007        firePropertyChange("action", oldValue, action);
1008        revalidate();
1009        repaint();
1010    }
1011    }
1012
1013    private boolean isListener(Class JavaDoc c, ActionListener a) {
1014    boolean isListener = false;
1015    Object JavaDoc[] listeners = listenerList.getListenerList();
1016        for (int i = listeners.length-2; i>=0; i-=2) {
1017            if (listeners[i]==c && listeners[i+1]==a) {
1018            isListener=true;
1019        }
1020    }
1021    return isListener;
1022    }
1023
1024    /**
1025     * Returns the currently set <code>Action</code> for this
1026     * <code>ActionEvent</code> source, or <code>null</code>
1027     * if no <code>Action</code> is set.
1028     *
1029     * @return the <code>Action</code> for this <code>ActionEvent</code>
1030     * source, or <code>null</code>
1031     * @since 1.3
1032     * @see Action
1033     * @see #setAction
1034     */

1035    public Action JavaDoc getAction() {
1036    return action;
1037    }
1038
1039    /**
1040     * Factory method which sets the <code>ActionEvent</code>
1041     * source's properties according to values from the
1042     * <code>Action</code> instance. The properties
1043     * which are set may differ for subclasses. By default,
1044     * the properties which get set are <code>Text, Icon,
1045     * Enabled, ToolTipText, ActionCommand</code>, and <code>Mnemonic</code>.
1046     * <p>
1047     * If the <code>Action</code> passed in is <code>null</code>,
1048     * the following things will occur:
1049     * <ul>
1050     * <li>the text is set to <code>null</code>,
1051     * <li>the icon is set to <code>null</code>,
1052     * <li>enabled is set to true,
1053     * <li>the tooltip text is set to <code>null</code>
1054     * </ul>
1055     *
1056     * @param a the <code>Action</code> from which to get the properties,
1057     * or <code>null</code>
1058     * @since 1.3
1059     * @see Action
1060     * @see #setAction
1061     */

1062    protected void configurePropertiesFromAction(Action JavaDoc a) {
1063        configurePropertiesFromAction(a, null);
1064    }
1065
1066    /**
1067     * Configures the AbstractButton's properties according to values
1068     * from the <code>Action</code> instance. Which properties to set
1069     * is determined by the <code>types</code> parameter.
1070     * <code>types</code> may hold the following keys:
1071     * <ul>
1072     * <li><code>Action.NAME</code> - set the <code>Text</code> property
1073     * from the <code>Action</code>,
1074     * <li><code>Action.SHORT_DESCRIPTION</code> - set the
1075     * <code>ToolTipText</code> property from the <code>Action</code>,
1076     * <li><code>Action.SMALL_ICON</code> - set the <code>Icon</code> property
1077     * from the <code>Action</code>,
1078     * <li><code>Action.MNEMONIC</code> - set the <code>Mnemonic</code>
1079     * property from the <code>Action</code>,
1080     * <li><code>Action.ACTION_COMMAND_KEY</code> - set the
1081     * <code>ActionCommand</code> property from the <code>Action</code>,
1082     * <li><code>"enabled"</code> - set <code>Enabled</code> property
1083     * from the <code>Action</code>
1084     * </ul>
1085     * <p>
1086     * If the <code>Action</code> passed in is <code>null</code>,
1087     * the following things will occur:
1088     * <ul>
1089     * <li>the text is set to <code>null</code>,
1090     * <li>the icon is set to <code>null</code>,
1091     * <li>enabled is set to true,
1092     * <li>the tooltip text is set to <code>null</code>
1093     * <li>the mnemonic is set to <code>'\0'</code>
1094     * </ul>
1095     *
1096     * @param a the <code>Action</code> from which to get the properties,
1097     * or <code>null</code>
1098     * @param types determines which properties to set from the
1099     * <code>Action</code>
1100     * @since 1.4
1101     * @see Action
1102     * @see #setAction
1103     * @see #configurePropertiesFromAction(javax.swing.Action)
1104     */

1105    void configurePropertiesFromAction(Action JavaDoc a, String JavaDoc[] types) {
1106        if (types == null) {
1107            String JavaDoc[] alltypes = { Action.MNEMONIC_KEY, Action.NAME,
1108                                  Action.SHORT_DESCRIPTION, Action.SMALL_ICON,
1109                                  Action.ACTION_COMMAND_KEY, "enabled" };
1110            types = alltypes;
1111        }
1112        for (int i=0; i<types.length; i++) {
1113            String JavaDoc type = types[i];
1114            if (type == null) continue;
1115
1116            if (type.equals(Action.MNEMONIC_KEY)) {
1117                Integer JavaDoc n = (a==null) ? null : (Integer JavaDoc)a.getValue(type);
1118                setMnemonic(n==null ? '\0' : n.intValue());
1119            } else if (type.equals(Action.NAME)) {
1120                // When hideActionText property is set, we don't use
1121
// Action name for button text. Useful for toolbar buttons.
1122
Boolean JavaDoc hide = (Boolean JavaDoc)getClientProperty("hideActionText");
1123                setText(a != null && hide!=Boolean.TRUE ?
1124                        (String JavaDoc)a.getValue(Action.NAME) :
1125                        null);
1126            } else if (type.equals(Action.SHORT_DESCRIPTION)) {
1127                setToolTipText(a!=null ? (String JavaDoc)a.getValue(type) : null);
1128            } else if (type.equals(Action.SMALL_ICON)) {
1129                setIcon(a!=null ? (Icon JavaDoc)a.getValue(type) : null);
1130            } else if (type.equals(Action.ACTION_COMMAND_KEY)) {
1131                setActionCommand(a!=null? (String JavaDoc)a.getValue(type) : null);
1132            } else if (type.equals("enabled")) {
1133                setEnabled(a!=null ? a.isEnabled() : true);
1134            }
1135        }
1136    }
1137
1138    /**
1139     * Factory method which creates the <code>PropertyChangeListener</code>
1140     * used to update the <code>ActionEvent</code> source as properties
1141     * change on its <code>Action</code> instance. Subclasses may
1142     * override this in order to provide their own
1143     * <code>PropertyChangeListener</code> if the set of
1144     * properties which should be kept up to date differs from the
1145     * default properties (<code>Text, Icon, Enabled, ToolTipText,
1146     * Mnemonic</code>).
1147     * <p>
1148     * Note that <code>PropertyChangeListeners</code> should avoid holding
1149     * strong references to the <code>ActionEvent</code> source,
1150     * as this may hinder garbage collection of the
1151     * <code>ActionEvent</code> source and all components
1152     * in its containment hierarchy.
1153     *
1154     * @param a the new action for the button
1155     * @since 1.3
1156     * @see Action
1157     * @see #setAction
1158     */

1159    protected PropertyChangeListener createActionPropertyChangeListener(Action JavaDoc a) {
1160        return new ButtonActionPropertyChangeListener(this, a);
1161    }
1162
1163    private static class ButtonActionPropertyChangeListener
1164                     extends AbstractActionPropertyChangeListener JavaDoc
1165                     implements Serializable JavaDoc {
1166    ButtonActionPropertyChangeListener(AbstractButton JavaDoc b, Action JavaDoc a) {
1167        super(b, a);
1168    }
1169    public void propertyChange(PropertyChangeEvent e) {
1170        String JavaDoc propertyName = e.getPropertyName();
1171        AbstractButton JavaDoc button = (AbstractButton JavaDoc)getTarget();
1172        if (button == null) { //WeakRef GC'ed in 1.2
1173
Action JavaDoc action = (Action JavaDoc)e.getSource();
1174        action.removePropertyChangeListener(this);
1175        } else {
1176            if (e.getPropertyName().equals(Action.NAME)) {
1177            Boolean JavaDoc hide = (Boolean JavaDoc)button.getClientProperty("hideActionText");
1178            if (hide == null || hide == Boolean.FALSE) {
1179                String JavaDoc text = (String JavaDoc) e.getNewValue();
1180                button.setText(text);
1181                button.repaint();
1182            }
1183            } else if (e.getPropertyName().equals(Action.SHORT_DESCRIPTION)) {
1184            String JavaDoc text = (String JavaDoc) e.getNewValue();
1185            button.setToolTipText(text);
1186            } else if (propertyName.equals("enabled")) {
1187            Boolean JavaDoc enabledState = (Boolean JavaDoc) e.getNewValue();
1188            button.setEnabled(enabledState.booleanValue());
1189            button.repaint();
1190            } else if (e.getPropertyName().equals(Action.SMALL_ICON)) {
1191            Icon JavaDoc icon = (Icon JavaDoc) e.getNewValue();
1192            button.setIcon(icon);
1193            button.invalidate();
1194            button.repaint();
1195            } else if (e.getPropertyName().equals(Action.MNEMONIC_KEY)) {
1196            Integer JavaDoc mn = (Integer JavaDoc) e.getNewValue();
1197            button.setMnemonic(mn.intValue());
1198            button.invalidate();
1199            button.repaint();
1200            } else if (e.getPropertyName().equals(Action.ACTION_COMMAND_KEY)) {
1201                        button.setActionCommand((String JavaDoc)e.getNewValue());
1202                    }
1203        }
1204    }
1205    }
1206
1207    /**
1208     * Gets the <code>borderPainted</code> property.
1209     *
1210     * @return the value of the <code>borderPainted</code> property
1211     * @see #setBorderPainted
1212     */

1213    public boolean isBorderPainted() {
1214        return paintBorder;
1215    }
1216    
1217    /**
1218     * Sets the <code>borderPainted</code> property.
1219     * If <code>true</code> and the button has a border,
1220     * the border is painted. The default value for the
1221     * <code>borderPainted</code> property is <code>true</code>.
1222     *
1223     * @param b if true and border property is not <code>null</code>,
1224     * the border is painted
1225     * @see #isBorderPainted
1226     * @beaninfo
1227     * bound: true
1228     * attribute: visualUpdate true
1229     * description: Whether the border should be painted.
1230     */

1231    public void setBorderPainted(boolean b) {
1232        boolean oldValue = paintBorder;
1233        paintBorder = b;
1234    borderPaintedSet = true;
1235        firePropertyChange(BORDER_PAINTED_CHANGED_PROPERTY, oldValue, paintBorder);
1236        if (b != oldValue) {
1237            revalidate();
1238            repaint();
1239        }
1240    }
1241
1242    /**
1243     * Paint the button's border if <code>BorderPainted</code>
1244     * property is true and the button has a border.
1245     * @param g the <code>Graphics</code> context in which to paint
1246     *
1247     * @see #paint
1248     * @see #setBorder
1249     */

1250    protected void paintBorder(Graphics g) {
1251        if (isBorderPainted()) {
1252            super.paintBorder(g);
1253        }
1254    }
1255 
1256    /**
1257     * Gets the <code>paintFocus</code> property.
1258     *
1259     * @return the <code>paintFocus</code> property
1260     * @see #setFocusPainted
1261     */

1262    public boolean isFocusPainted() {
1263        return paintFocus;
1264    }
1265    
1266    /**
1267     * Sets the <code>paintFocus</code> property, which must
1268     * be <code>true</code> for the focus state to be painted.
1269     * The default value for the <code>paintFocus</code> property
1270     * is <code>true</code>.
1271     * Some look and feels might not paint focus state;
1272     * they will ignore this property.
1273     *
1274     * @param b if <code>true</code>, the focus state should be painted
1275     * @see #isFocusPainted
1276     * @beaninfo
1277     * bound: true
1278     * attribute: visualUpdate true
1279     * description: Whether focus should be painted
1280     */

1281    public void setFocusPainted(boolean b) {
1282        boolean oldValue = paintFocus;
1283        paintFocus = b;
1284        firePropertyChange(FOCUS_PAINTED_CHANGED_PROPERTY, oldValue, paintFocus);
1285        if (b != oldValue && isFocusOwner()) {
1286            revalidate();
1287            repaint();
1288        }
1289    }
1290
1291    /**
1292     * Gets the <code>contentAreaFilled</code> property.
1293     *
1294     * @return the <code>contentAreaFilled</code> property
1295     * @see #setContentAreaFilled
1296     */

1297    public boolean isContentAreaFilled() {
1298        return contentAreaFilled;
1299    }
1300    
1301    /**
1302     * Sets the <code>contentAreaFilled</code> property.
1303     * If <code>true</code> the button will paint the content
1304     * area. If you wish to have a transparent button, such as
1305     * an icon only button, for example, then you should set
1306     * this to <code>false</code>. Do not call <code>setOpaque(false)</code>.
1307     * The default value for the the <code>contentAreaFilled</code>
1308     * property is <code>true</code>.
1309     * <p>
1310     * This function may cause the component's opaque property to change.
1311     * <p>
1312     * The exact behavior of calling this function varies on a
1313     * component-by-component and L&F-by-L&F basis.
1314     *
1315     * @param b if true, the content should be filled; if false
1316     * the content area is not filled
1317     * @see #isContentAreaFilled
1318     * @see #setOpaque
1319     * @beaninfo
1320     * bound: true
1321     * attribute: visualUpdate true
1322     * description: Whether the button should paint the content area
1323     * or leave it transparent.
1324     */

1325    public void setContentAreaFilled(boolean b) {
1326        boolean oldValue = contentAreaFilled;
1327        contentAreaFilled = b;
1328    contentAreaFilledSet = true;
1329        firePropertyChange(CONTENT_AREA_FILLED_CHANGED_PROPERTY, oldValue, contentAreaFilled);
1330        if (b != oldValue) {
1331            repaint();
1332        }
1333    }
1334
1335    /**
1336     * Gets the <code>rolloverEnabled</code> property.
1337     *
1338     * @return the value of the <code>rolloverEnabled</code> property
1339     * @see #setRolloverEnabled
1340     */

1341    public boolean isRolloverEnabled() {
1342        return rolloverEnabled;
1343    }
1344    
1345    /**
1346     * Sets the <code>rolloverEnabled</code> property, which
1347     * must be <code>true</code> for rollover effects to occur.
1348     * The default value for the <code>rolloverEnabled</code>
1349     * property is <code>false</code>.
1350     * Some look and feels might not implement rollover effects;
1351     * they will ignore this property.
1352     *
1353     * @param b if <code>true</code>, rollover effects should be painted
1354     * @see #isRolloverEnabled
1355     * @beaninfo
1356     * bound: true
1357     * attribute: visualUpdate true
1358     * description: Whether rollover effects should be enabled.
1359     */

1360    public void setRolloverEnabled(boolean b) {
1361        boolean oldValue = rolloverEnabled;
1362        rolloverEnabled = b;
1363        rolloverEnabledSet = true;
1364        firePropertyChange(ROLLOVER_ENABLED_CHANGED_PROPERTY, oldValue, rolloverEnabled);
1365        if (b != oldValue) {
1366            repaint();
1367        }
1368    }
1369
1370    /**
1371     * Returns the keyboard mnemonic from the the current model.
1372     * @return the keyboard mnemonic from the model
1373     */

1374    public int getMnemonic() {
1375        return mnemonic;
1376    }
1377
1378    /**
1379     * Sets the keyboard mnemonic on the current model.
1380     * The mnemonic is the key which when combined with the look and feel's
1381     * mouseless modifier (usually Alt) will activate this button
1382     * if focus is contained somewhere within this button's ancestor
1383     * window.
1384     * <p>
1385     * A mnemonic must correspond to a single key on the keyboard
1386     * and should be specified using one of the <code>VK_XXX</code>
1387     * keycodes defined in <code>java.awt.event.KeyEvent</code>.
1388     * Mnemonics are case-insensitive, therefore a key event
1389     * with the corresponding keycode would cause the button to be
1390     * activated whether or not the Shift modifier was pressed.
1391     * <p>
1392     * If the character defined by the mnemonic is found within
1393     * the button's label string, the first occurrence of it
1394     * will be underlined to indicate the mnemonic to the user.
1395     *
1396     * @param mnemonic the key code which represents the mnemonic
1397     * @see java.awt.event.KeyEvent
1398     * @see #setDisplayedMnemonicIndex
1399     *
1400     * @beaninfo
1401     * bound: true
1402     * attribute: visualUpdate true
1403     * description: the keyboard character mnemonic
1404     */

1405    public void setMnemonic(int mnemonic) {
1406        int oldValue = getMnemonic();
1407        model.setMnemonic(mnemonic);
1408        updateMnemonicProperties();
1409    }
1410
1411    /**
1412     * This method is now obsolete, please use <code>setMnemonic(int)</code>
1413     * to set the mnemonic for a button. This method is only designed
1414     * to handle character values which fall between 'a' and 'z' or
1415     * 'A' and 'Z'.
1416     *
1417     * @param mnemonic a char specifying the mnemonic value
1418     * @see #setMnemonic(int)
1419     * @beaninfo
1420     * bound: true
1421     * attribute: visualUpdate true
1422     * description: the keyboard character mnemonic
1423     */

1424    public void setMnemonic(char mnemonic) {
1425        int vk = (int) mnemonic;
1426        if(vk >= 'a' && vk <='z')
1427            vk -= ('a' - 'A');
1428        setMnemonic(vk);
1429    }
1430
1431    /**
1432     * Provides a hint to the look and feel as to which character in the
1433     * text should be decorated to represent the mnemonic. Not all look and
1434     * feels may support this. A value of -1 indicates either there is no
1435     * mnemonic, the mnemonic character is not contained in the string, or
1436     * the developer does not wish the mnemonic to be displayed.
1437     * <p>
1438     * The value of this is updated as the properties relating to the
1439     * mnemonic change (such as the mnemonic itself, the text...).
1440     * You should only ever have to call this if
1441     * you do not wish the default character to be underlined. For example, if
1442     * the text was 'Save As', with a mnemonic of 'a', and you wanted the 'A'
1443     * to be decorated, as 'Save <u>A</u>s', you would have to invoke
1444     * <code>setDisplayedMnemonicIndex(5)</code> after invoking
1445     * <code>setMnemonic(KeyEvent.VK_A)</code>.
1446     *
1447     * @since 1.4
1448     * @param index Index into the String to underline
1449     * @exception IllegalArgumentException will be thrown if <code>index</code>
1450     * is &gt;= length of the text, or &lt; -1
1451     * @see #getDisplayedMnemonicIndex
1452     *
1453     * @beaninfo
1454     * bound: true
1455     * attribute: visualUpdate true
1456     * description: the index into the String to draw the keyboard character
1457     * mnemonic at
1458     */

1459    public void setDisplayedMnemonicIndex(int index)
1460                                          throws IllegalArgumentException JavaDoc {
1461        int oldValue = mnemonicIndex;
1462        if (index == -1) {
1463            mnemonicIndex = -1;
1464        } else {
1465            String JavaDoc text = getText();
1466            int textLength = (text == null) ? 0 : text.length();
1467            if (index < -1 || index >= textLength) { // index out of range
1468
throw new IllegalArgumentException JavaDoc("index == " + index);
1469            }
1470        }
1471        mnemonicIndex = index;
1472        firePropertyChange("displayedMnemonicIndex", oldValue, index);
1473        if (index != oldValue) {
1474            revalidate();
1475            repaint();
1476        }
1477    }
1478
1479    /**
1480     * Returns the character, as an index, that the look and feel should
1481     * provide decoration for as representing the mnemonic character.
1482     *
1483     * @since 1.4
1484     * @return index representing mnemonic character
1485     * @see #setDisplayedMnemonicIndex
1486     */

1487    public int getDisplayedMnemonicIndex() {
1488        return mnemonicIndex;
1489    }
1490
1491    /**
1492     * Update the displayedMnemonicIndex property. This method
1493     * is called when either text or mnemonic changes. The new
1494     * value of the displayedMnemonicIndex property is the index
1495     * of the first occurrence of mnemonic in text.
1496     */

1497    private void updateDisplayedMnemonicIndex(String JavaDoc text, int mnemonic) {
1498        setDisplayedMnemonicIndex(
1499            SwingUtilities.findDisplayedMnemonicIndex(text, mnemonic));
1500    }
1501
1502    /**
1503     * Brings the mnemonic property in accordance with model's mnemonic.
1504     * This is called when model's mnemonic changes. Also updates the
1505     * displayedMnemonicIndex property.
1506     */

1507    private void updateMnemonicProperties() {
1508        int newMnemonic = model.getMnemonic();
1509        if (mnemonic != newMnemonic) {
1510            int oldValue = mnemonic;
1511            mnemonic = newMnemonic;
1512            firePropertyChange(MNEMONIC_CHANGED_PROPERTY,
1513                               oldValue, mnemonic);
1514            updateDisplayedMnemonicIndex(getText(), mnemonic);
1515            revalidate();
1516            repaint();
1517        }
1518    }
1519
1520    /**
1521     * Sets the amount of time (in milliseconds) required between
1522     * mouse press events for the button to generate the corresponding
1523     * action events. After the initial mouse press occurs (and action
1524     * event generated) any subsequent mouse press events which occur
1525     * on intervals less than the threshhold will be ignored and no
1526     * corresponding action event generated. By default the threshhold is 0,
1527     * which means that for each mouse press, an action event will be
1528     * fired, no matter how quickly the mouse clicks occur. In buttons
1529     * where this behavior is not desirable (for example, the "OK" button
1530     * in a dialog), this threshhold should be set to an appropriate
1531     * positive value.
1532     *
1533     * @see #getMultiClickThreshhold
1534     * @param threshhold the amount of time required between mouse
1535     * press events to generate corresponding action events
1536     * @exception IllegalArgumentException if threshhold < 0
1537     * @since 1.4
1538     */

1539    public void setMultiClickThreshhold(long threshhold) {
1540    if (threshhold < 0) {
1541        throw new IllegalArgumentException JavaDoc("threshhold must be >= 0");
1542    }
1543    this.multiClickThreshhold = threshhold;
1544    }
1545
1546    /**
1547     * Gets the amount of time (in milliseconds) required between
1548     * mouse press events for the button to generate the corresponding
1549     * action events.
1550     *
1551     * @see #setMultiClickThreshhold
1552     * @return the amount of time required between mouse press events
1553     * to generate corresponding action events
1554     * @since 1.4
1555     */

1556    public long getMultiClickThreshhold() {
1557    return multiClickThreshhold;
1558    }
1559
1560    /**
1561     * Returns the model that this button represents.
1562     * @return the <code>model</code> property
1563     * @see #setModel
1564     */

1565    public ButtonModel JavaDoc getModel() {
1566        return model;
1567    }
1568    
1569    /**
1570     * Sets the model that this button represents.
1571     * @param newModel the new <code>ButtonModel</code>
1572     * @see #getModel
1573     * @beaninfo
1574     * bound: true
1575     * description: Model that the Button uses.
1576     */

1577    public void setModel(ButtonModel JavaDoc newModel) {
1578        
1579        ButtonModel JavaDoc oldModel = getModel();
1580        
1581        if (oldModel != null) {
1582            oldModel.removeChangeListener(changeListener);
1583            oldModel.removeActionListener(actionListener);
1584            oldModel.removeItemListener(itemListener);
1585            changeListener = null;
1586            actionListener = null;
1587            itemListener = null;
1588        }
1589        
1590        model = newModel;
1591        
1592        if (newModel != null) {
1593            changeListener = createChangeListener();
1594            actionListener = createActionListener();
1595            itemListener = createItemListener();
1596            newModel.addChangeListener(changeListener);
1597            newModel.addActionListener(actionListener);
1598            newModel.addItemListener(itemListener);
1599
1600            updateMnemonicProperties();
1601        } else {
1602            mnemonic = '\0';
1603        }
1604
1605        updateDisplayedMnemonicIndex(getText(), mnemonic);
1606
1607        firePropertyChange(MODEL_CHANGED_PROPERTY, oldModel, newModel);
1608        if (newModel != oldModel) {
1609            revalidate();
1610            repaint();
1611        }
1612    }
1613
1614    
1615    /**
1616     * Returns the L&F object that renders this component.
1617     * @return the ButtonUI object
1618     * @see #setUI
1619     */

1620    public ButtonUI getUI() {
1621        return (ButtonUI) ui;
1622    }
1623
1624    
1625    /**
1626     * Sets the L&F object that renders this component.
1627     * @param ui the <code>ButtonUI</code> L&F object
1628     * @see #getUI
1629     * @beaninfo
1630     * bound: true
1631     * hidden: true
1632     * attribute: visualUpdate true
1633     * description: The UI object that implements the LookAndFeel.
1634     */

1635    public void setUI(ButtonUI ui) {
1636        super.setUI(ui);
1637        // disabled icons are generated by the LF so they should be unset here
1638
if (disabledIcon instanceof UIResource) {
1639            setDisabledIcon(null);
1640        }
1641        if (disabledSelectedIcon instanceof UIResource) {
1642            setDisabledSelectedIcon(null);
1643        }
1644    }
1645
1646    
1647    /**
1648     * Resets the UI property to a value from the current look
1649     * and feel. Subtypes of <code>AbstractButton</code>
1650     * should override this to update the UI. For
1651     * example, <code>JButton</code> might do the following:
1652     * <pre>
1653     * setUI((ButtonUI)UIManager.getUI(
1654     * "ButtonUI", "javax.swing.plaf.basic.BasicButtonUI", this));
1655     * </pre>
1656     */

1657    public void updateUI() {
1658    }
1659    
1660    /**
1661     * Adds the specified component to this container at the specified
1662     * index, refer to
1663     * {@link java.awt.Container#addImpl(Component, Object, int)}
1664     * for a complete description of this method.
1665     *
1666     * @param comp the component to be added
1667     * @param constraints an object expressing layout constraints
1668     * for this component
1669     * @param index the position in the container's list at which to
1670     * insert the component, where <code>-1</code>
1671     * means append to the end
1672     * @exception IllegalArgumentException if <code>index</code> is invalid
1673     * @exception IllegalArgumentException if adding the container's parent
1674     * to itself
1675     * @exception IllegalArgumentException if adding a window to a container
1676     * @since 1.5
1677     */

1678    protected void addImpl(Component comp, Object JavaDoc constraints, int index) {
1679        if (!setLayout) {
1680            setLayout(new OverlayLayout JavaDoc(this));
1681        }
1682        super.addImpl(comp, constraints, index);
1683    }
1684
1685    /**
1686     * Sets the layout manager for this container, refer to
1687     * {@link java.awt.Container#setLayout(LayoutManager)}
1688     * for a complete description of this method.
1689     *
1690     * @param mgr the specified layout manager
1691     * @since 1.5
1692     */

1693    public void setLayout(LayoutManager mgr) {
1694        setLayout = true;
1695        super.setLayout(mgr);
1696    }
1697
1698    /**
1699     * Adds a <code>ChangeListener</code> to the button.
1700     * @param l the listener to be added
1701     */

1702    public void addChangeListener(ChangeListener l) {
1703        listenerList.add(ChangeListener.class, l);
1704    }
1705    
1706    /**
1707     * Removes a ChangeListener from the button.
1708     * @param l the listener to be removed
1709     */

1710    public void removeChangeListener(ChangeListener l) {
1711        listenerList.remove(ChangeListener.class, l);
1712    }
1713    
1714    /**
1715     * Returns an array of all the <code>ChangeListener</code>s added
1716     * to this AbstractButton with addChangeListener().
1717     *
1718     * @return all of the <code>ChangeListener</code>s added or an empty
1719     * array if no listeners have been added
1720     * @since 1.4
1721     */

1722    public ChangeListener[] getChangeListeners() {
1723        return (ChangeListener[])(listenerList.getListeners(
1724            ChangeListener.class));
1725    }
1726
1727    /**
1728     * Notifies all listeners that have registered interest for
1729     * notification on this event type. The event instance
1730     * is lazily created.
1731     * @see EventListenerList
1732     */

1733    protected void fireStateChanged() {
1734        // Guaranteed to return a non-null array
1735
Object JavaDoc[] listeners = listenerList.getListenerList();
1736        // Process the listeners last to first, notifying
1737
// those that are interested in this event
1738
for (int i = listeners.length-2; i>=0; i-=2) {
1739            if (listeners[i]==ChangeListener.class) {
1740                // Lazily create the event:
1741
if (changeEvent == null)
1742                    changeEvent = new ChangeEvent(this);
1743                ((ChangeListener)listeners[i+1]).stateChanged(changeEvent);
1744            }
1745        }
1746    }
1747
1748    /**
1749     * Adds an <code>ActionListener</code> to the button.
1750     * @param l the <code>ActionListener</code> to be added
1751     */

1752    public void addActionListener(ActionListener l) {
1753        listenerList.add(ActionListener.class, l);
1754    }
1755    
1756    /**
1757     * Removes an <code>ActionListener</code> from the button.
1758     * If the listener is the currently set <code>Action</code>
1759     * for the button, then the <code>Action</code>
1760     * is set to <code>null</code>.
1761     *
1762     * @param l the listener to be removed
1763     */

1764    public void removeActionListener(ActionListener l) {
1765    if ((l != null) && (getAction() == l)) {
1766        setAction(null);
1767    } else {
1768        listenerList.remove(ActionListener.class, l);
1769    }
1770    }
1771    
1772    /**
1773     * Returns an array of all the <code>ActionListener</code>s added
1774     * to this AbstractButton with addActionListener().
1775     *
1776     * @return all of the <code>ActionListener</code>s added or an empty
1777     * array if no listeners have been added
1778     * @since 1.4
1779     */

1780    public ActionListener[] getActionListeners() {
1781        return (ActionListener[])(listenerList.getListeners(
1782            ActionListener.class));
1783    }
1784    
1785    /**
1786     * Subclasses that want to handle <code>ChangeEvents</code> differently
1787     * can override this to return another <code>ChangeListener</code>
1788     * implementation.
1789     *
1790     * @return the new <code>ChangeListener</code>
1791     */

1792    protected ChangeListener createChangeListener() {
1793        return getHandler();
1794    }
1795
1796    /**
1797     * Extends <code>ChangeListener</code> to be serializable.
1798     * <p>
1799     * <strong>Warning:</strong>
1800     * Serialized objects of this class will not be compatible with
1801     * future Swing releases. The current serialization support is
1802     * appropriate for short term storage or RMI between applications running
1803     * the same version of Swing. As of 1.4, support for long term storage
1804     * of all JavaBeans<sup><font size="-2">TM</font></sup>
1805     * has been added to the <code>java.beans</code> package.
1806     * Please see {@link java.beans.XMLEncoder}.
1807     */

1808    protected class ButtonChangeListener implements ChangeListener, Serializable JavaDoc {
1809        // NOTE: This class is NOT used, instead the functionality has
1810
// been moved to Handler.
1811
ButtonChangeListener() {
1812        }
1813
1814        public void stateChanged(ChangeEvent e) {
1815            getHandler().stateChanged(e);
1816        }
1817    }
1818
1819
1820    /**
1821     * Notifies all listeners that have registered interest for
1822     * notification on this event type. The event instance
1823     * is lazily created using the <code>event</code>
1824     * parameter.
1825     *
1826     * @param event the <code>ActionEvent</code> object
1827     * @see EventListenerList
1828     */

1829    protected void fireActionPerformed(ActionEvent event) {
1830        // Guaranteed to return a non-null array
1831
Object JavaDoc[] listeners = listenerList.getListenerList();
1832        ActionEvent e = null;
1833        // Process the listeners last to first, notifying
1834
// those that are interested in this event
1835
for (int i = listeners.length-2; i>=0; i-=2) {
1836            if (listeners[i]==ActionListener.class) {
1837                // Lazily create the event:
1838
if (e == null) {
1839                      String JavaDoc actionCommand = event.getActionCommand();
1840                      if(actionCommand == null) {
1841                         actionCommand = getActionCommand();
1842                      }
1843                      e = new ActionEvent(AbstractButton.this,
1844                                          ActionEvent.ACTION_PERFORMED,
1845                                          actionCommand,
1846                                          event.getWhen(),
1847                                          event.getModifiers());
1848                }
1849                ((ActionListener)listeners[i+1]).actionPerformed(e);
1850            }
1851        }
1852    }
1853    
1854    /**
1855     * Notifies all listeners that have registered interest for
1856     * notification on this event type. The event instance
1857     * is lazily created using the <code>event</code> parameter.
1858     *
1859     * @param event the <code>ItemEvent</code> object
1860     * @see EventListenerList
1861     */

1862    protected void fireItemStateChanged(ItemEvent event) {
1863        // Guaranteed to return a non-null array
1864
Object JavaDoc[] listeners = listenerList.getListenerList();
1865        ItemEvent e = null;
1866        // Process the listeners last to first, notifying
1867
// those that are interested in this event
1868
for (int i = listeners.length-2; i>=0; i-=2) {
1869            if (listeners[i]==ItemListener.class) {
1870                // Lazily create the event:
1871
if (e == null) {
1872                    e = new ItemEvent(AbstractButton.this,
1873                                      ItemEvent.ITEM_STATE_CHANGED,
1874                                      AbstractButton.this,
1875                                      event.getStateChange());
1876                }
1877                ((ItemListener)listeners[i+1]).itemStateChanged(e);
1878            }
1879        }
1880    if (accessibleContext != null) {
1881        if (event.getStateChange() == ItemEvent.SELECTED) {
1882        accessibleContext.firePropertyChange(
1883                AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
1884                    null, AccessibleState.SELECTED);
1885        accessibleContext.firePropertyChange(
1886                AccessibleContext.ACCESSIBLE_VALUE_PROPERTY,
1887                    new Integer JavaDoc(0), new Integer JavaDoc(1));
1888        } else {
1889        accessibleContext.firePropertyChange(
1890                AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
1891                    AccessibleState.SELECTED, null);
1892        accessibleContext.firePropertyChange(
1893                AccessibleContext.ACCESSIBLE_VALUE_PROPERTY,
1894                    new Integer JavaDoc(1), new Integer JavaDoc(0));
1895        }
1896    }
1897    }
1898    
1899
1900    protected ActionListener createActionListener() {
1901        return getHandler();
1902    }
1903
1904
1905    protected ItemListener createItemListener() {
1906        return getHandler();
1907    }
1908
1909    
1910    /**
1911     * Enables (or disables) the button.
1912     * @param b true to enable the button, otherwise false
1913     */

1914    public void setEnabled(boolean b) {
1915    if (!b && model.isRollover()) {
1916        model.setRollover(false);
1917    }
1918        super.setEnabled(b);
1919        model.setEnabled(b);
1920    }
1921
1922    // *** Deprecated java.awt.Button APIs below *** //
1923

1924    /**
1925     * Returns the label text.
1926     *
1927     * @return a <code>String</code> containing the label
1928     * @deprecated - Replaced by <code>getText</code>
1929     */

1930    @Deprecated JavaDoc
1931    public String JavaDoc getLabel() {
1932        return getText();
1933    }
1934    
1935    /**
1936     * Sets the label text.
1937     *
1938     * @param label a <code>String</code> containing the text
1939     * @deprecated - Replaced by <code>setText(text)</code>
1940     * @beaninfo
1941     * bound: true
1942     * description: Replace by setText(text)
1943     */

1944    @Deprecated JavaDoc
1945    public void setLabel(String JavaDoc label) {
1946        setText(label);
1947    }
1948
1949    /**
1950     * Adds an <code>ItemListener</code> to the <code>checkbox</code>.
1951     * @param l the <code>ItemListener</code> to be added
1952     */

1953    public void addItemListener(ItemListener l) {
1954        listenerList.add(ItemListener.class, l);
1955    }
1956    
1957    /**
1958     * Removes an <code>ItemListener</code> from the button.
1959     * @param l the <code>ItemListener</code> to be removed
1960     */

1961    public void removeItemListener(ItemListener l) {
1962        listenerList.remove(ItemListener.class, l);
1963    }
1964
1965    /**
1966     * Returns an array of all the <code>ItemListener</code>s added
1967     * to this AbstractButton with addItemListener().
1968     *
1969     * @return all of the <code>ItemListener</code>s added or an empty
1970     * array if no listeners have been added
1971     * @since 1.4
1972     */

1973    public ItemListener[] getItemListeners() {
1974        return (ItemListener[])listenerList.getListeners(ItemListener.class);
1975    }
1976
1977   /**
1978     * Returns an array (length 1) containing the label or
1979     * <code>null</code> if the button is not selected.
1980     *
1981     * @return an array containing 1 Object: the text of the button,
1982     * if the item is selected; otherwise <code>null</code>
1983     */

1984    public Object JavaDoc[] getSelectedObjects() {
1985        if (isSelected() == false) {
1986            return null;
1987        }
1988        Object JavaDoc[] selectedObjects = new Object JavaDoc[1];
1989        selectedObjects[0] = getText();
1990        return selectedObjects;
1991    }
1992
1993    protected void init(String JavaDoc text, Icon JavaDoc icon) {
1994        if(text != null) {
1995            setText(text);
1996        }
1997        
1998        if(icon != null) {
1999            setIcon(icon);
2000        }
2001        
2002        // Set the UI
2003
updateUI();
2004
2005        setAlignmentX(LEFT_ALIGNMENT);
2006        setAlignmentY(CENTER_ALIGNMENT);
2007    }
2008
2009
2010    /**
2011     * This is overridden to return false if the current <code>Icon</code>'s
2012     * <code>Image</code> is not equal to the
2013     * passed in <code>Image</code> <code>img</code>.
2014     *
2015     * @param img the <code>Image</code> to be compared
2016     * @param infoflags flags used to repaint the button when the image
2017     * is updated and which determine how much is to be painted
2018     * @param x the x coordinate
2019     * @param y the y coordinate
2020     * @param w the width
2021     * @param h the height
2022     * @see java.awt.image.ImageObserver
2023     * @see java.awt.Component#imageUpdate(java.awt.Image, int, int, int, int, int)
2024     */

2025    public boolean imageUpdate(Image img, int infoflags,
2026                   int x, int y, int w, int h) {
2027        Icon JavaDoc iconDisplayed = getIcon();
2028        if (iconDisplayed == null) {
2029            return false;
2030        }
2031
2032        if (!model.isEnabled()) {
2033            if (model.isSelected()) {
2034                iconDisplayed = getDisabledSelectedIcon();
2035            } else {
2036                iconDisplayed = getDisabledIcon();
2037            }
2038        } else if (model.isPressed() && model.isArmed()) {
2039            iconDisplayed = getPressedIcon();
2040        } else if (isRolloverEnabled() && model.isRollover()) {
2041            if (model.isSelected()) {
2042                iconDisplayed = getRolloverSelectedIcon();
2043            } else {
2044                iconDisplayed = getRolloverIcon();
2045            }
2046        } else if (model.isSelected()) {
2047            iconDisplayed = getSelectedIcon();
2048        }
2049
2050    if (!SwingUtilities.doesIconReferenceImage(iconDisplayed, img)) {
2051        // We don't know about this image, disable the notification so
2052
// we don't keep repainting.
2053
return false;
2054    }
2055    return super.imageUpdate(img, infoflags, x, y, w, h);
2056    }
2057
2058    void setUIProperty(String JavaDoc propertyName, Object JavaDoc value) {
2059        if (propertyName == "borderPainted") {
2060        if (!borderPaintedSet) {
2061        setBorderPainted(((Boolean JavaDoc)value).booleanValue());
2062        borderPaintedSet = false;
2063        }
2064    } else if (propertyName == "rolloverEnabled") {
2065        if (!rolloverEnabledSet) {
2066        setRolloverEnabled(((Boolean JavaDoc)value).booleanValue());
2067        rolloverEnabledSet = false;
2068        }
2069    } else if (propertyName == "iconTextGap") {
2070        if (!iconTextGapSet) {
2071        setIconTextGap(((Number JavaDoc)value).intValue());
2072        iconTextGapSet = false;
2073        }
2074    } else if (propertyName == "contentAreaFilled") {
2075        if (!contentAreaFilledSet) {
2076        setContentAreaFilled(((Boolean JavaDoc)value).booleanValue());
2077        contentAreaFilledSet = false;
2078        }
2079    } else {
2080        super.setUIProperty(propertyName, value);
2081    }
2082    }
2083
2084    /**
2085     * Returns a string representation of this <code>AbstractButton</code>.
2086     * This method
2087     * is intended to be used only for debugging purposes, and the
2088     * content and format of the returned string may vary between
2089     * implementations. The returned string may be empty but may not
2090     * be <code>null</code>.
2091     * <P>
2092     * Overriding <code>paramString</code> to provide information about the
2093     * specific new aspects of the JFC components.
2094     *
2095     * @return a string representation of this <code>AbstractButton</code>
2096     */

2097    protected String JavaDoc paramString() {
2098    String JavaDoc defaultIconString = ((defaultIcon != null)
2099                    && (defaultIcon != this) ?
2100                    defaultIcon.toString() : "");
2101    String JavaDoc pressedIconString = ((pressedIcon != null)
2102                    && (pressedIcon != this) ?
2103                    pressedIcon.toString() : "");
2104    String JavaDoc disabledIconString = ((disabledIcon != null)
2105                     && (disabledIcon != this) ?
2106                     disabledIcon.toString() : "");
2107    String JavaDoc selectedIconString = ((selectedIcon != null)
2108                     && (selectedIcon != this) ?
2109                     selectedIcon.toString() : "");
2110    String JavaDoc disabledSelectedIconString = ((disabledSelectedIcon != null) &&
2111                         (disabledSelectedIcon != this) ?
2112                         disabledSelectedIcon.toString()
2113                         : "");
2114    String JavaDoc rolloverIconString = ((rolloverIcon != null)
2115                     && (rolloverIcon != this) ?
2116                     rolloverIcon.toString() : "");
2117    String JavaDoc rolloverSelectedIconString = ((rolloverSelectedIcon != null) &&
2118                         (rolloverSelectedIcon != this) ?
2119                         rolloverSelectedIcon.toString()
2120                         : "");
2121    String JavaDoc paintBorderString = (paintBorder ? "true" : "false");
2122    String JavaDoc paintFocusString = (paintFocus ? "true" : "false");
2123    String JavaDoc rolloverEnabledString = (rolloverEnabled ? "true" : "false");
2124
2125    return super.paramString() +
2126    ",defaultIcon=" + defaultIconString +
2127    ",disabledIcon=" + disabledIconString +
2128    ",disabledSelectedIcon=" + disabledSelectedIconString +
2129    ",margin=" + margin +
2130    ",paintBorder=" + paintBorderString +
2131    ",paintFocus=" + paintFocusString +
2132    ",pressedIcon=" + pressedIconString +
2133    ",rolloverEnabled=" + rolloverEnabledString +
2134    ",rolloverIcon=" + rolloverIconString +
2135    ",rolloverSelectedIcon=" + rolloverSelectedIconString +
2136    ",selectedIcon=" + selectedIconString +
2137    ",text=" + text;
2138    }
2139
2140
2141    private Handler getHandler() {
2142        if (handler == null) {
2143            handler = new Handler();
2144        }
2145        return handler;
2146    }
2147
2148
2149    //
2150
// Listeners that are added to model
2151
//
2152
class Handler implements ActionListener, ChangeListener, ItemListener,
2153                             Serializable JavaDoc {
2154        //
2155
// ChangeListener
2156
//
2157
public void stateChanged(ChangeEvent e) {
2158            Object JavaDoc source = e.getSource();
2159
2160            updateMnemonicProperties();
2161            fireStateChanged();
2162            repaint();
2163        }
2164
2165        //
2166
// ActionListener
2167
//
2168
public void actionPerformed(ActionEvent event) {
2169            fireActionPerformed(event);
2170        }
2171
2172        //
2173
// ItemListener
2174
//
2175
public void itemStateChanged(ItemEvent event) {
2176            fireItemStateChanged(event);
2177        }
2178    }
2179
2180///////////////////
2181
// Accessibility support
2182
///////////////////
2183
/**
2184     * This class implements accessibility support for the
2185     * <code>AbstractButton</code> class. It provides an implementation of the
2186     * Java Accessibility API appropriate to button and menu item
2187     * user-interface elements.
2188     * <p>
2189     * <strong>Warning:</strong>
2190     * Serialized objects of this class will not be compatible with
2191     * future Swing releases. The current serialization support is
2192     * appropriate for short term storage or RMI between applications running
2193     * the same version of Swing. As of 1.4, support for long term storage
2194     * of all JavaBeans<sup><font size="-2">TM</font></sup>
2195     * has been added to the <code>java.beans</code> package.
2196     * Please see {@link java.beans.XMLEncoder}.
2197     */

2198    protected abstract class AccessibleAbstractButton
2199        extends AccessibleJComponent implements AccessibleAction,
2200        AccessibleValue, AccessibleText, AccessibleExtendedComponent {
2201
2202        /**
2203         * Returns the accessible name of this object.
2204         *
2205         * @return the localized name of the object -- can be
2206         * <code>null</code> if this
2207         * object does not have a name
2208         */

2209        public String JavaDoc getAccessibleName() {
2210            if (accessibleName != null) {
2211                return accessibleName;
2212            } else {
2213                if (AbstractButton.this.getText() == null) {
2214                    return super.getAccessibleName();
2215                } else {
2216                    return AbstractButton.this.getText();
2217                }
2218            }
2219        }
2220
2221    /**
2222     * Get the AccessibleIcons associated with this object if one
2223     * or more exist. Otherwise return null.
2224     */

2225    public AccessibleIcon [] getAccessibleIcon() {
2226            Icon JavaDoc defaultIcon = getIcon();
2227
2228            if (defaultIcon instanceof Accessible) {
2229                AccessibleContext ac =
2230                    ((Accessible)defaultIcon).getAccessibleContext();
2231                if (ac != null && ac instanceof AccessibleIcon) {
2232                    return new AccessibleIcon[] { (AccessibleIcon)ac };
2233                }
2234            }
2235            return null;
2236    }
2237
2238        /**
2239         * Get the state set of this object.
2240         *
2241         * @return an instance of AccessibleState containing the current state
2242         * of the object
2243         * @see AccessibleState
2244         */

2245        public AccessibleStateSet getAccessibleStateSet() {
2246        AccessibleStateSet states = super.getAccessibleStateSet();
2247            if (getModel().isArmed()) {
2248                states.add(AccessibleState.ARMED);
2249            }
2250            if (isFocusOwner()) {
2251                states.add(AccessibleState.FOCUSED);
2252            }
2253            if (getModel().isPressed()) {
2254                states.add(AccessibleState.PRESSED);
2255            }
2256            if (isSelected()) {
2257                states.add(AccessibleState.CHECKED);
2258            }
2259            return states;
2260        }
2261
2262        /**
2263         * Get the AccessibleRelationSet associated with this object if one
2264         * exists. Otherwise return null.
2265         * @see AccessibleRelation
2266         */

2267        public AccessibleRelationSet getAccessibleRelationSet() {
2268
2269        // Check where the AccessibleContext's relation
2270
// set already contains a MEMBER_OF relation.
2271
AccessibleRelationSet relationSet
2272        = super.getAccessibleRelationSet();
2273
2274        if (!relationSet.contains(AccessibleRelation.MEMBER_OF)) {
2275        // get the members of the button group if one exists
2276
ButtonModel JavaDoc model = getModel();
2277        if (model != null && model instanceof DefaultButtonModel JavaDoc) {
2278            ButtonGroup JavaDoc group = ((DefaultButtonModel JavaDoc)model).getGroup();
2279            if (group != null) {
2280            // set the target of the MEMBER_OF relation to be
2281
// the members of the button group.
2282
int len = group.getButtonCount();
2283            Object JavaDoc [] target = new Object JavaDoc[len];
2284            Enumeration JavaDoc elem = group.getElements();
2285            for (int i = 0; i < len; i++) {
2286                if (elem.hasMoreElements()) {
2287                target[i] = elem.nextElement();
2288                }
2289            }
2290            AccessibleRelation relation =
2291                new AccessibleRelation(AccessibleRelation.MEMBER_OF);
2292            relation.setTarget(target);
2293            relationSet.add(relation);
2294            }
2295        }
2296        }
2297        return relationSet;
2298        }
2299
2300        /**
2301         * Get the AccessibleAction associated with this object. In the
2302         * implementation of the Java Accessibility API for this class,
2303     * return this object, which is responsible for implementing the
2304         * AccessibleAction interface on behalf of itself.
2305     *
2306     * @return this object
2307         */

2308        public AccessibleAction getAccessibleAction() {
2309            return this;
2310        }
2311
2312        /**
2313         * Get the AccessibleValue associated with this object. In the
2314         * implementation of the Java Accessibility API for this class,
2315     * return this object, which is responsible for implementing the
2316         * AccessibleValue interface on behalf of itself.
2317     *
2318     * @return this object
2319         */

2320        public AccessibleValue getAccessibleValue() {
2321            return this;
2322        }
2323
2324        /**
2325         * Returns the number of Actions available in this object. The
2326         * default behavior of a button is to have one action - toggle
2327         * the button.
2328         *
2329         * @return 1, the number of Actions in this object
2330         */

2331        public int getAccessibleActionCount() {
2332            return 1;
2333        }
2334    
2335        /**
2336         * Return a description of the specified action of the object.
2337         *
2338         * @param i zero-based index of the actions
2339         */

2340        public String JavaDoc getAccessibleActionDescription(int i) {
2341            if (i == 0) {
2342                return UIManager.getString("AbstractButton.clickText");
2343            } else {
2344                return null;
2345            }
2346        }
2347    
2348        /**
2349         * Perform the specified Action on the object
2350         *
2351         * @param i zero-based index of actions
2352         * @return true if the the action was performed; else false.
2353         */

2354        public boolean doAccessibleAction(int i) {
2355            if (i == 0) {
2356                doClick();
2357                return true;
2358            } else {
2359                return false;
2360            }
2361        }
2362
2363        /**
2364         * Get the value of this object as a Number.
2365         *
2366         * @return An Integer of 0 if this isn't selected or an Integer of 1 if
2367         * this is selected.
2368         * @see AbstractButton#isSelected
2369         */

2370        public Number JavaDoc getCurrentAccessibleValue() {
2371            if (isSelected()) {
2372                return new Integer JavaDoc(1);
2373            } else {
2374                return new Integer JavaDoc(0);
2375            }
2376        }
2377
2378        /**
2379         * Set the value of this object as a Number.
2380         *
2381         * @return True if the value was set.
2382         */

2383        public boolean setCurrentAccessibleValue(Number JavaDoc n) {
2384        // TIGER - 4422535
2385
if (n == null) {
2386        return false;
2387        }
2388        int i = n.intValue();
2389        if (i == 0) {
2390        setSelected(false);
2391        } else {
2392        setSelected(true);
2393        }
2394        return true;
2395        }
2396
2397        /**
2398         * Get the minimum value of this object as a Number.
2399         *
2400         * @return an Integer of 0.
2401         */

2402        public Number JavaDoc getMinimumAccessibleValue() {
2403            return new Integer JavaDoc(0);
2404        }
2405
2406        /**
2407         * Get the maximum value of this object as a Number.
2408         *
2409         * @return An Integer of 1.
2410         */

2411        public Number JavaDoc getMaximumAccessibleValue() {
2412            return new Integer JavaDoc(1);
2413        }
2414
2415
2416    /* AccessibleText ---------- */
2417        
2418    public AccessibleText getAccessibleText() {
2419        View view = (View)AbstractButton.this.getClientProperty("html");
2420        if (view != null) {
2421        return this;
2422        } else {
2423        return null;
2424        }
2425    }
2426
2427    /**
2428     * Given a point in local coordinates, return the zero-based index
2429     * of the character under that Point. If the point is invalid,
2430     * this method returns -1.
2431     *
2432         * Note: the AbstractButton must have a valid size (e.g. have
2433         * been added to a parent container whose ancestor container
2434         * is a valid top-level window) for this method to be able
2435         * to return a meaningful value.
2436     *
2437     * @param p the Point in local coordinates
2438     * @return the zero-based index of the character under Point p; if
2439     * Point is invalid returns -1.
2440     */

2441    public int getIndexAtPoint(Point p) {
2442        View view = (View) AbstractButton.this.getClientProperty("html");
2443        if (view != null) {
2444        Rectangle r = getTextRectangle();
2445        if (r == null) {
2446            return -1;
2447        }
2448        Rectangle2D.Float shape =
2449            new Rectangle2D.Float(r.x, r.y, r.width, r.height);
2450        Position.Bias bias[] = new Position.Bias[1];
2451        return view.viewToModel(p.x, p.y, shape, bias);
2452        } else {
2453        return -1;
2454        }
2455    }
2456    
2457    /**
2458     * Determine the bounding box of the character at the given
2459     * index into the string. The bounds are returned in local
2460     * coordinates. If the index is invalid an empty rectangle is
2461     * returned.
2462     *
2463         * Note: the AbstractButton must have a valid size (e.g. have
2464         * been added to a parent container whose ancestor container
2465         * is a valid top-level window) for this method to be able
2466         * to return a meaningful value.
2467     *
2468     * @param i the index into the String
2469     * @return the screen coordinates of the character's the bounding box,
2470     * if index is invalid returns an empty rectangle.
2471     */

2472    public Rectangle getCharacterBounds(int i) {
2473        View view = (View) AbstractButton.this.getClientProperty("html");
2474        if (view != null) {
2475        Rectangle r = getTextRectangle();
2476        if (r == null) {
2477            return null;
2478        }
2479        Rectangle2D.Float shape =
2480            new Rectangle2D.Float(r.x, r.y, r.width, r.height);
2481        try {
2482            Shape charShape =
2483            view.modelToView(i, shape, Position.Bias.Forward);
2484            return charShape.getBounds();
2485        } catch (BadLocationException e) {
2486            return null;
2487        }
2488        } else {
2489        return null;
2490        }
2491    }
2492    
2493    /**
2494     * Return the number of characters (valid indicies)
2495     *
2496     * @return the number of characters
2497     */

2498    public int getCharCount() {
2499        View view = (View) AbstractButton.this.getClientProperty("html");
2500        if (view != null) {
2501        Document d = view.getDocument();
2502        if (d instanceof StyledDocument) {
2503            StyledDocument doc = (StyledDocument)d;
2504            return doc.getLength();
2505        }
2506        }
2507        return accessibleContext.getAccessibleName().length();
2508    }
2509    
2510    /**
2511     * Return the zero-based offset of the caret.
2512     *
2513     * Note: That to the right of the caret will have the same index
2514     * value as the offset (the caret is between two characters).
2515     * @return the zero-based offset of the caret.
2516     */

2517    public int getCaretPosition() {
2518        // There is no caret.
2519
return -1;
2520    }
2521    
2522        /**
2523         * Returns the String at a given index.
2524         *
2525         * @param part the AccessibleText.CHARACTER, AccessibleText.WORD,
2526         * or AccessibleText.SENTENCE to retrieve
2527         * @param index an index within the text >= 0
2528         * @return the letter, word, or sentence,
2529         * null for an invalid index or part
2530         */

2531        public String JavaDoc getAtIndex(int part, int index) {
2532            if (index < 0 || index >= getCharCount()) {
2533                return null;
2534            }
2535            switch (part) {
2536            case AccessibleText.CHARACTER:
2537                try {
2538                    return getText(index, 1);
2539                } catch (BadLocationException e) {
2540                    return null;
2541                }
2542            case AccessibleText.WORD:
2543                try {
2544                    String JavaDoc s = getText(0, getCharCount());
2545                    BreakIterator words = BreakIterator.getWordInstance(getLocale());
2546                    words.setText(s);
2547                    int end = words.following(index);
2548                    return s.substring(words.previous(), end);
2549                } catch (BadLocationException e) {
2550                    return null;
2551                }
2552            case AccessibleText.SENTENCE:
2553                try {
2554                    String JavaDoc s = getText(0, getCharCount());
2555                    BreakIterator sentence =
2556            BreakIterator.getSentenceInstance(getLocale());
2557                    sentence.setText(s);
2558                    int end = sentence.following(index);
2559                    return s.substring(sentence.previous(), end);
2560                } catch (BadLocationException e) {
2561                    return null;
2562                }
2563            default:
2564                return null;
2565            }
2566        }
2567
2568        /**
2569         * Returns the String after a given index.
2570         *
2571         * @param part the AccessibleText.CHARACTER, AccessibleText.WORD,
2572         * or AccessibleText.SENTENCE to retrieve
2573         * @param index an index within the text >= 0
2574         * @return the letter, word, or sentence, null for an invalid
2575         * index or part
2576         */

2577        public String JavaDoc getAfterIndex(int part, int index) {
2578            if (index < 0 || index >= getCharCount()) {
2579                return null;
2580            }
2581            switch (part) {
2582            case AccessibleText.CHARACTER:
2583        if (index+1 >= getCharCount()) {
2584           return null;
2585        }
2586                try {
2587                    return getText(index+1, 1);
2588                } catch (BadLocationException e) {
2589                    return null;
2590                }
2591            case AccessibleText.WORD:
2592                try {
2593                    String JavaDoc s = getText(0, getCharCount());
2594                    BreakIterator words = BreakIterator.getWordInstance(getLocale());
2595                    words.setText(s);
2596                    int start = words.following(index);
2597            if (start == BreakIterator.DONE || start >= s.length()) {
2598            return null;
2599            }
2600            int end = words.following(start);
2601            if (end == BreakIterator.DONE || end >= s.length()) {
2602            return null;
2603            }
2604                    return s.substring(start, end);
2605                } catch (BadLocationException e) {
2606                    return null;
2607                }
2608            case AccessibleText.SENTENCE:
2609                try {
2610                    String JavaDoc s = getText(0, getCharCount());
2611                    BreakIterator sentence =
2612            BreakIterator.getSentenceInstance(getLocale());
2613                    sentence.setText(s);
2614                    int start = sentence.following(index);
2615            if (start == BreakIterator.DONE || start >= s.length()) {
2616            return null;
2617            }
2618            int end = sentence.following(start);
2619            if (end == BreakIterator.DONE || end >= s.length()) {
2620            return null;
2621            }
2622                    return s.substring(start, end);
2623                } catch (BadLocationException e) {
2624                    return null;
2625                }
2626            default:
2627                return null;
2628            }
2629        }
2630
2631        /**
2632         * Returns the String before a given index.
2633         *
2634         * @param part the AccessibleText.CHARACTER, AccessibleText.WORD,
2635         * or AccessibleText.SENTENCE to retrieve
2636         * @param index an index within the text >= 0
2637         * @return the letter, word, or sentence, null for an invalid index
2638         * or part
2639         */

2640        public String JavaDoc getBeforeIndex(int part, int index) {
2641            if (index < 0 || index > getCharCount()-1) {
2642                return null;
2643            }
2644            switch (part) {
2645            case AccessibleText.CHARACTER:
2646        if (index == 0) {
2647            return null;
2648        }
2649                try {
2650                    return getText(index-1, 1);
2651                } catch (BadLocationException e) {
2652                    return null;
2653                }
2654            case AccessibleText.WORD:
2655                try {
2656                    String JavaDoc s = getText(0, getCharCount());
2657                    BreakIterator words = BreakIterator.getWordInstance(getLocale());
2658                    words.setText(s);
2659                    int end = words.following(index);
2660                    end = words.previous();
2661            int start = words.previous();
2662            if (start == BreakIterator.DONE) {
2663            return null;
2664            }
2665                    return s.substring(start, end);
2666                } catch (BadLocationException e) {
2667                    return null;
2668                }
2669            case AccessibleText.SENTENCE:
2670                try {
2671                    String JavaDoc s = getText(0, getCharCount());
2672                    BreakIterator sentence =
2673            BreakIterator.getSentenceInstance(getLocale());
2674                    sentence.setText(s);
2675                    int end = sentence.following(index);
2676                    end = sentence.previous();
2677            int start = sentence.previous();
2678            if (start == BreakIterator.DONE) {
2679            return null;
2680            }
2681                    return s.substring(start, end);
2682                } catch (BadLocationException e) {
2683                    return null;
2684                }
2685            default:
2686                return null;
2687            }
2688        }
2689
2690    /**
2691     * Return the AttributeSet for a given character at a given index
2692     *
2693     * @param i the zero-based index into the text
2694     * @return the AttributeSet of the character
2695     */

2696    public AttributeSet getCharacterAttribute(int i) {
2697        View view = (View) AbstractButton.this.getClientProperty("html");
2698        if (view != null) {
2699        Document d = view.getDocument();
2700        if (d instanceof StyledDocument) {
2701            StyledDocument doc = (StyledDocument)d;
2702            Element elem = doc.getCharacterElement(i);
2703            if (elem != null) {
2704            return elem.getAttributes();
2705            }
2706        }
2707        }
2708        return null;
2709    }
2710
2711    /**
2712     * Returns the start offset within the selected text.
2713     * If there is no selection, but there is
2714     * a caret, the start and end offsets will be the same.
2715     *
2716     * @return the index into the text of the start of the selection
2717     */

2718    public int getSelectionStart() {
2719        // Text cannot be selected.
2720
return -1;
2721    }
2722
2723    /**
2724     * Returns the end offset within the selected text.
2725     * If there is no selection, but there is
2726     * a caret, the start and end offsets will be the same.
2727     *
2728     * @return the index into teh text of the end of the selection
2729     */

2730    public int getSelectionEnd() {
2731        // Text cannot be selected.
2732
return -1;
2733    }
2734
2735    /**
2736     * Returns the portion of the text that is selected.
2737     *
2738     * @return the String portion of the text that is selected
2739     */

2740    public String JavaDoc getSelectedText() {
2741        // Text cannot be selected.
2742
return null;
2743    }
2744
2745    /*
2746     * Returns the text substring starting at the specified
2747     * offset with the specified length.
2748     */

2749    private String JavaDoc getText(int offset, int length)
2750        throws BadLocationException {
2751
2752        View view = (View) AbstractButton.this.getClientProperty("html");
2753        if (view != null) {
2754        Document d = view.getDocument();
2755        if (d instanceof StyledDocument) {
2756            StyledDocument doc = (StyledDocument)d;
2757            return doc.getText(offset, length);
2758        }
2759        }
2760        return null;
2761    }
2762
2763    /*
2764     * Returns the bounding rectangle for the component text.
2765     */

2766    private Rectangle getTextRectangle() {
2767        
2768        String JavaDoc text = AbstractButton.this.getText();
2769        Icon JavaDoc icon = (AbstractButton.this.isEnabled()) ? AbstractButton.this.getIcon() : AbstractButton.this.getDisabledIcon();
2770        
2771        if ((icon == null) && (text == null)) {
2772        return null;
2773        }
2774
2775        Rectangle paintIconR = new Rectangle();
2776        Rectangle paintTextR = new Rectangle();
2777        Rectangle paintViewR = new Rectangle();
2778        Insets paintViewInsets = new Insets(0, 0, 0, 0);
2779
2780        paintViewInsets = AbstractButton.this.getInsets(paintViewInsets);
2781        paintViewR.x = paintViewInsets.left;
2782        paintViewR.y = paintViewInsets.top;
2783        paintViewR.width = AbstractButton.this.getWidth() - (paintViewInsets.left + paintViewInsets.right);
2784        paintViewR.height = AbstractButton.this.getHeight() - (paintViewInsets.top + paintViewInsets.bottom);
2785        
2786        Graphics g = AbstractButton.this.getGraphics();
2787        if (g == null) {
2788        return null;
2789        }
2790        String JavaDoc clippedText = SwingUtilities.layoutCompoundLabel(
2791            (JComponent JavaDoc)AbstractButton.this,
2792        g.getFontMetrics(),
2793        text,
2794        icon,
2795        AbstractButton.this.getVerticalAlignment(),
2796        AbstractButton.this.getHorizontalAlignment(),
2797        AbstractButton.this.getVerticalTextPosition(),
2798        AbstractButton.this.getHorizontalTextPosition(),
2799        paintViewR,
2800        paintIconR,
2801        paintTextR,
2802        0);
2803
2804        return paintTextR;
2805    }
2806
2807    // ----- AccessibleExtendedComponent
2808

2809    /**
2810     * Returns the AccessibleExtendedComponent
2811     *
2812     * @return the AccessibleExtendedComponent
2813     */

2814    AccessibleExtendedComponent getAccessibleExtendedComponent() {
2815        return this;
2816    }
2817
2818    /**
2819     * Returns the tool tip text
2820     *
2821     * @return the tool tip text, if supported, of the object;
2822     * otherwise, null
2823     */

2824    public String JavaDoc getToolTipText() {
2825        return AbstractButton.this.getToolTipText();
2826    }
2827    
2828    /**
2829     * Returns the titled border text
2830     *
2831     * @return the titled border text, if supported, of the object;
2832     * otherwise, null
2833     */

2834    public String JavaDoc getTitledBorderText() {
2835        return super.getTitledBorderText();
2836    }
2837        
2838    /**
2839     * Returns key bindings associated with this object
2840     *
2841     * @return the key bindings, if supported, of the object;
2842     * otherwise, null
2843     * @see AccessibleKeyBinding
2844     */

2845    public AccessibleKeyBinding getAccessibleKeyBinding() {
2846        int mnemonic = AbstractButton.this.getMnemonic();
2847        if (mnemonic == 0) {
2848        return null;
2849        }
2850        return new ButtonKeyBinding(mnemonic);
2851    }
2852
2853    class ButtonKeyBinding implements AccessibleKeyBinding {
2854        int mnemonic;
2855
2856        ButtonKeyBinding(int mnemonic) {
2857        this.mnemonic = mnemonic;
2858        }
2859
2860        /**
2861         * Returns the number of key bindings for this object
2862         *
2863         * @return the zero-based number of key bindings for this object
2864         */

2865        public int getAccessibleKeyBindingCount() {
2866        return 1;
2867        }
2868        
2869        /**
2870         * Returns a key binding for this object. The value returned is an
2871         * java.lang.Object which must be cast to appropriate type depending
2872         * on the underlying implementation of the key. For example, if the
2873         * Object returned is a javax.swing.KeyStroke, the user of this
2874         * method should do the following:
2875         * <nf><code>
2876         * Component c = <get the component that has the key bindings>
2877         * AccessibleContext ac = c.getAccessibleContext();
2878         * AccessibleKeyBinding akb = ac.getAccessibleKeyBinding();
2879         * for (int i = 0; i < akb.getAccessibleKeyBindingCount(); i++) {
2880         * Object o = akb.getAccessibleKeyBinding(i);
2881         * if (o instanceof javax.swing.KeyStroke) {
2882         * javax.swing.KeyStroke keyStroke = (javax.swing.KeyStroke)o;
2883         * <do something with the key binding>
2884         * }
2885         * }
2886         * </code></nf>
2887         *
2888         * @param i zero-based index of the key bindings
2889         * @return a javax.lang.Object which specifies the key binding
2890         * @exception IllegalArgumentException if the index is
2891         * out of bounds
2892         * @see #getAccessibleKeyBindingCount
2893         */

2894        public java.lang.Object JavaDoc getAccessibleKeyBinding(int i) {
2895        if (i != 0) {
2896            throw new IllegalArgumentException JavaDoc();
2897        }
2898        return KeyStroke.getKeyStroke(mnemonic, 0);
2899        }
2900    }
2901    }
2902}
2903
Popular Tags