1 /* AbstractButton.java -- Provides basic button functionality.
2 Copyright (C) 2002, 2004 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
40 import java.awt.Graphics;
41 import java.awt.Image;
42 import java.awt.Insets;
43 import java.awt.ItemSelectable;
44 import java.awt.Point;
45 import java.awt.Rectangle;
46 import java.awt.event.ActionEvent;
47 import java.awt.event.ActionListener;
48 import java.awt.event.ItemEvent;
49 import java.awt.event.ItemListener;
50 import java.awt.image.ImageObserver;
51 import java.beans.PropertyChangeEvent;
52 import java.beans.PropertyChangeListener;
53 import java.io.Serializable;
55 import javax.accessibility.AccessibleAction;
56 import javax.accessibility.AccessibleIcon;
57 import javax.accessibility.AccessibleRelationSet;
58 import javax.accessibility.AccessibleStateSet;
59 import javax.accessibility.AccessibleText;
60 import javax.accessibility.AccessibleValue;
61 import javax.swing.event.ChangeEvent;
62 import javax.swing.event.ChangeListener;
63 import javax.swing.plaf.ButtonUI;
64 import javax.swing.text.AttributeSet;
68 * Provides an abstract implementation of common button behaviour,
69 * data model and look & feel.
71 * <p>This class is supposed to serve as a base class for
72 * several kinds of buttons with similar but non-identical semantics:
73 * toggle buttons (radio buttons and checkboxes), simple push buttons,
74 * menu items, etc.</p>
76 * <p>Buttons have many properties, some of which are stored in this class
77 * while others are delegated to the button's model. The following properties
81 * <tr><th>Property </th><th>Stored in</th><th>Bound?</th></tr>
83 * <tr><td>action </td><td>button</td> <td>no</td></tr>
84 * <tr><td>actionCommand </td><td>model</td> <td>no</td></tr>
85 * <tr><td>borderPainted </td><td>button</td> <td>yes</td></tr>
86 * <tr><td>contentAreaFilled </td><td>button</td> <td>yes</td></tr>
87 * <tr><td>disabledIcon </td><td>button</td> <td>yes</td></tr>
88 * <tr><td>disabledSelectedIcon </td><td>button</td> <td>yes</td></tr>
89 * <tr><td>displayedMnemonicIndex </td><td>button</td> <td>no</td></tr>
90 * <tr><td>enabled </td><td>model</td> <td>no</td></tr>
91 * <tr><td>focusPainted </td><td>button</td> <td>yes</td></tr>
92 * <tr><td>horizontalAlignment </td><td>button</td> <td>yes</td></tr>
93 * <tr><td>horizontalTextPosition </td><td>button</td> <td>yes</td></tr>
94 * <tr><td>icon </td><td>button</td> <td>yes</td></tr>
95 * <tr><td>iconTextGap </td><td>button</td> <td>no</td></tr>
96 * <tr><td>label (same as text) </td><td>model</td> <td>yes</td></tr>
97 * <tr><td>margin </td><td>button</td> <td>yes</td></tr>
98 * <tr><td>multiClickThreshold </td><td>button</td> <td>no</td></tr>
99 * <tr><td>pressedIcon </td><td>button</td> <td>yes</td></tr>
100 * <tr><td>rolloverEnabled </td><td>button</td> <td>yes</td></tr>
101 * <tr><td>rolloverIcon </td><td>button</td> <td>yes</td></tr>
102 * <tr><td>rolloverSelectedIcon </td><td>button</td> <td>yes</td></tr>
103 * <tr><td>selected </td><td>model</td> <td>no</td></tr>
104 * <tr><td>selectedIcon </td><td>button</td> <td>yes</td></tr>
105 * <tr><td>selectedObjects </td><td>button</td> <td>no</td></tr>
106 * <tr><td>text </td><td>model</td> <td>yes</td></tr>
107 * <tr><td>UI </td><td>button</td> <td>yes</td></tr>
108 * <tr><td>verticalAlignment </td><td>button</td> <td>yes</td></tr>
109 * <tr><td>verticalTextPosition </td><td>button</td> <td>yes</td></tr>
113 * <p>The various behavioral aspects of these properties follows:</p>
117 * <li>When non-bound properties stored in the button change, the button
118 * fires ChangeEvents to its ChangeListeners.</li>
120 * <li>When bound properties stored in the button change, the button fires
121 * PropertyChangeEvents to its PropertyChangeListeners</li>
123 * <li>If any of the model's properties change, it fires a ChangeEvent to
124 * its ChangeListeners, which include the button.</li>
126 * <li>If the button receives a ChangeEvent from its model, it will
127 * propagate the ChangeEvent to its ChangeListeners, with the ChangeEvent's
128 * "source" property set to refer to the button, rather than the model. The
129 * the button will request a repaint, to paint its updated state.</li>
131 * <li>If the model's "selected" property changes, the model will fire an
132 * ItemEvent to its ItemListeners, which include the button, in addition to
133 * the ChangeEvent which models the property change. The button propagates
134 * ItemEvents directly to its ItemListeners.</li>
136 * <li>If the model's armed and pressed properties are simultaneously
137 * <code>true</code>, the model will fire an ActionEvent to its
138 * ActionListeners, which include the button. The button will propagate
139 * this ActionEvent to its ActionListeners, with the ActionEvent's "source"
140 * property set to refer to the button, rather than the model.</li>
144 * @author Ronald Veldema (rveldema@cs.vu.nl)
145 * @author Graydon Hoare (graydon@redhat.com)
148 public abstract class AbstractButton extends JComponent
149 implements ItemSelectable, SwingConstants
151 private static final long serialVersionUID = -937921345538462020L;
154 * An extension of ChangeListener to be serializable.
156 protected class ButtonChangeListener
157 implements ChangeListener, Serializable
159 private static final long serialVersionUID = 1471056094226600578L;
162 * The spec has no public/protected constructor for this class, so do we.
164 ButtonChangeListener()
166 // Nothing to do here.
170 * Notified when the target of the listener changes its state.
172 * @param ev the ChangeEvent describing the change
174 public void stateChanged(ChangeEvent ev)
176 AbstractButton.this.fireStateChanged();
181 /** The icon displayed by default. */
184 /** The icon displayed when the button is pressed. */
187 /** The icon displayed when the button is disabled. */
190 /** The icon displayed when the button is selected. */
193 /** The icon displayed when the button is selected but disabled. */
194 Icon disabledSelectedIcon;
196 /** The icon displayed when the button is rolled over. */
199 /** The icon displayed when the button is selected and rolled over. */
200 Icon rolloverSelectedIcon;
202 /** The icon currently displayed. */
205 /** The text displayed in the button. */
209 * The gap between icon and text, if both icon and text are
210 * non-<code>null</code>.
214 /** The vertical alignment of the button's text and icon. */
215 int verticalAlignment;
217 /** The horizontal alignment of the button's text and icon. */
218 int horizontalAlignment;
220 /** The horizontal position of the button's text relative to its icon. */
221 int horizontalTextPosition;
223 /** The vertical position of the button's text relative to its icon. */
224 int verticalTextPosition;
226 /** Whether or not the button paints its border. */
227 boolean borderPainted;
229 /** Whether or not the button paints its focus state. */
230 boolean focusPainted;
232 /** Whether or not the button fills its content area. */
233 boolean contentAreaFilled;
235 /** Whether rollover is enabled. */
236 boolean rollOverEnabled;
238 /** The action taken when the button is clicked. */
241 /** The button's current state. */
242 protected ButtonModel model;
244 /** The margin between the button's border and its label. */
248 * A hint to the look and feel class, suggesting which character in the
249 * button's label should be underlined when drawing the label.
253 /** Listener the button uses to receive ActionEvents from its model. */
254 protected ActionListener actionListener;
256 /** Listener the button uses to receive ItemEvents from its model. */
257 protected ItemListener itemListener;
259 /** Listener the button uses to receive ChangeEvents from its model. */
260 protected ChangeListener changeListener;
263 * The time in miliseconds in which clicks get coalesced into a single
264 * <code>ActionEvent</code>.
266 long multiClickThreshhold;
269 * Listener the button uses to receive PropertyChangeEvents from its
272 PropertyChangeListener actionPropertyChangeListener;
274 /** ChangeEvent that is fired to button's ChangeEventListeners */
275 protected ChangeEvent changeEvent = new ChangeEvent(this);
278 * Fired in a PropertyChangeEvent when the "borderPainted" property changes.
280 public static final String BORDER_PAINTED_CHANGED_PROPERTY = "borderPainted";
283 * Fired in a PropertyChangeEvent when the "contentAreaFilled" property
286 public static final String CONTENT_AREA_FILLED_CHANGED_PROPERTY =
290 * Fired in a PropertyChangeEvent when the "disabledIcon" property changes.
292 public static final String DISABLED_ICON_CHANGED_PROPERTY = "disabledIcon";
295 * Fired in a PropertyChangeEvent when the "disabledSelectedIcon" property
298 public static final String DISABLED_SELECTED_ICON_CHANGED_PROPERTY =
299 "disabledSelectedIcon";
302 * Fired in a PropertyChangeEvent when the "focusPainted" property changes.
304 public static final String FOCUS_PAINTED_CHANGED_PROPERTY = "focusPainted";
307 * Fired in a PropertyChangeEvent when the "horizontalAlignment" property
310 public static final String HORIZONTAL_ALIGNMENT_CHANGED_PROPERTY =
311 "horizontalAlignment";
314 * Fired in a PropertyChangeEvent when the "horizontalTextPosition" property
317 public static final String HORIZONTAL_TEXT_POSITION_CHANGED_PROPERTY =
318 "horizontalTextPosition";
321 * Fired in a PropertyChangeEvent when the "icon" property changes. */
322 public static final String ICON_CHANGED_PROPERTY = "icon";
324 /** Fired in a PropertyChangeEvent when the "margin" property changes. */
325 public static final String MARGIN_CHANGED_PROPERTY = "margin";
327 /** Fired in a PropertyChangeEvent when the "mnemonic" property changes. */
328 public static final String MNEMONIC_CHANGED_PROPERTY = "mnemonic";
330 /** Fired in a PropertyChangeEvent when the "model" property changes. */
331 public static final String MODEL_CHANGED_PROPERTY = "model";
333 /** Fired in a PropertyChangeEvent when the "pressedIcon" property changes. */
334 public static final String PRESSED_ICON_CHANGED_PROPERTY = "pressedIcon";
337 * Fired in a PropertyChangeEvent when the "rolloverEnabled" property
340 public static final String ROLLOVER_ENABLED_CHANGED_PROPERTY =
344 * Fired in a PropertyChangeEvent when the "rolloverIcon" property changes.
346 public static final String ROLLOVER_ICON_CHANGED_PROPERTY = "rolloverIcon";
349 * Fired in a PropertyChangeEvent when the "rolloverSelectedIcon" property
352 public static final String ROLLOVER_SELECTED_ICON_CHANGED_PROPERTY =
353 "rolloverSelectedIcon";
356 * Fired in a PropertyChangeEvent when the "selectedIcon" property changes.
358 public static final String SELECTED_ICON_CHANGED_PROPERTY = "selectedIcon";
360 /** Fired in a PropertyChangeEvent when the "text" property changes. */
361 public static final String TEXT_CHANGED_PROPERTY = "text";
364 * Fired in a PropertyChangeEvent when the "verticalAlignment" property
367 public static final String VERTICAL_ALIGNMENT_CHANGED_PROPERTY =
371 * Fired in a PropertyChangeEvent when the "verticalTextPosition" property
374 public static final String VERTICAL_TEXT_POSITION_CHANGED_PROPERTY =
375 "verticalTextPosition";
378 * A Java Accessibility extension of the AbstractButton.
380 protected abstract class AccessibleAbstractButton
381 extends AccessibleJComponent implements AccessibleAction, AccessibleValue,
384 private static final long serialVersionUID = -5673062525319836790L;
386 protected AccessibleAbstractButton()
388 // Nothing to do here yet.
391 public AccessibleStateSet getAccessibleStateSet()
396 public String getAccessibleName()
401 public AccessibleIcon[] getAccessibleIcon()
406 public AccessibleRelationSet getAccessibleRelationSet()
411 public AccessibleAction getAccessibleAction()
416 public AccessibleValue getAccessibleValue()
421 public int getAccessibleActionCount()
426 public String getAccessibleActionDescription(int value0)
431 public boolean doAccessibleAction(int value0)
433 return false; // TODO
436 public Number getCurrentAccessibleValue()
441 public boolean setCurrentAccessibleValue(Number value0)
443 return false; // TODO
446 public Number getMinimumAccessibleValue()
451 public Number getMaximumAccessibleValue()
456 public AccessibleText getAccessibleText()
461 public int getIndexAtPoint(Point value0)
466 public Rectangle getCharacterBounds(int value0)
471 public int getCharCount()
476 public int getCaretPosition()
481 public String getAtIndex(int value0, int value1)
486 public String getAfterIndex(int value0, int value1)
491 public String getBeforeIndex(int value0, int value1)
496 public AttributeSet getCharacterAttribute(int value0)
501 public int getSelectionStart()
506 public int getSelectionEnd()
511 public String getSelectedText()
516 private Rectangle getTextRectangle()
523 * Creates a new AbstractButton object. Subclasses should call the following
524 * sequence in their constructor in order to initialize the button correctly:
530 * The {@link #init(String, Icon)} method is not called automatically by this
533 * @see #init(String, Icon)
535 public AbstractButton()
537 actionListener = createActionListener();
538 changeListener = createChangeListener();
539 itemListener = createItemListener();
541 horizontalAlignment = CENTER;
542 horizontalTextPosition = TRAILING;
543 verticalAlignment = CENTER;
544 verticalTextPosition = CENTER;
545 borderPainted = true;
546 contentAreaFilled = true;
549 setAlignmentX(CENTER_ALIGNMENT);
550 setAlignmentY(CENTER_ALIGNMENT);
551 setDisplayedMnemonicIndex(-1);
558 * Get the model the button is currently using.
560 * @return The current model
562 public ButtonModel getModel()
568 * Set the model the button is currently using. This un-registers all
569 * listeners associated with the current model, and re-registers them
570 * with the new model.
572 * @param newModel The new model
574 public void setModel(ButtonModel newModel)
576 if (newModel == model)
581 model.removeActionListener(actionListener);
582 model.removeChangeListener(changeListener);
583 model.removeItemListener(itemListener);
585 ButtonModel old = model;
589 model.addActionListener(actionListener);
590 model.addChangeListener(changeListener);
591 model.addItemListener(itemListener);
593 firePropertyChange(MODEL_CHANGED_PROPERTY, old, model);
598 protected void init(String text, Icon icon)
600 // If text is null, we fall back to the empty
601 // string (which is set using AbstractButton's
603 // This way the behavior of the JDK is matched.
612 * <p>Returns the action command string for this button's model.</p>
614 * <p>If the action command was set to <code>null</code>, the button's
615 * text (label) is returned instead.</p>
617 * @return The current action command string from the button's model
619 public String getActionCommand()
621 String ac = model.getActionCommand();
629 * Sets the action command string for this button's model.
631 * @param actionCommand The new action command string to set in the button's
634 public void setActionCommand(String actionCommand)
637 model.setActionCommand(actionCommand);
641 * Adds an ActionListener to the button's listener list. When the
642 * button's model is clicked it fires an ActionEvent, and these
643 * listeners will be called.
645 * @param l The new listener to add
647 public void addActionListener(ActionListener l)
649 listenerList.add(ActionListener.class, l);
653 * Removes an ActionListener from the button's listener list.
655 * @param l The listener to remove
657 public void removeActionListener(ActionListener l)
659 listenerList.remove(ActionListener.class, l);
663 * Returns all added <code>ActionListener</code> objects.
665 * @return an array of listeners
669 public ActionListener[] getActionListeners()
671 return (ActionListener[]) listenerList.getListeners(ActionListener.class);
675 * Adds an ItemListener to the button's listener list. When the button's
676 * model changes state (between any of ARMED, ENABLED, PRESSED, ROLLOVER
677 * or SELECTED) it fires an ItemEvent, and these listeners will be
680 * @param l The new listener to add
682 public void addItemListener(ItemListener l)
684 listenerList.add(ItemListener.class, l);
688 * Removes an ItemListener from the button's listener list.
690 * @param l The listener to remove
692 public void removeItemListener(ItemListener l)
694 listenerList.remove(ItemListener.class, l);
698 * Returns all added <code>ItemListener</code> objects.
700 * @return an array of listeners
704 public ItemListener[] getItemListeners()
706 return (ItemListener[]) listenerList.getListeners(ItemListener.class);
710 * Adds a ChangeListener to the button's listener list. When the button's
711 * model changes any of its (non-bound) properties, these listeners will be
714 * @param l The new listener to add
716 public void addChangeListener(ChangeListener l)
718 listenerList.add(ChangeListener.class, l);
722 * Removes a ChangeListener from the button's listener list.
724 * @param l The listener to remove
726 public void removeChangeListener(ChangeListener l)
728 listenerList.remove(ChangeListener.class, l);
732 * Returns all added <code>ChangeListener</code> objects.
734 * @return an array of listeners
738 public ChangeListener[] getChangeListeners()
740 return (ChangeListener[]) listenerList.getListeners(ChangeListener.class);
744 * Calls {@link ItemListener#itemStateChanged} on each ItemListener in
745 * the button's listener list.
747 * @param e The event signifying that the button's model changed state
749 protected void fireItemStateChanged(ItemEvent e)
752 ItemListener[] listeners = getItemListeners();
754 for (int i = 0; i < listeners.length; i++)
755 listeners[i].itemStateChanged(e);
759 * Calls {@link ActionListener#actionPerformed} on each {@link
760 * ActionListener} in the button's listener list.
762 * @param e The event signifying that the button's model was clicked
764 protected void fireActionPerformed(ActionEvent e)
766 // Dispatch a copy of the given ActionEvent in order to
767 // set the source and action command correctly.
768 ActionEvent ae = new ActionEvent(
775 ActionListener[] listeners = getActionListeners();
777 for (int i = 0; i < listeners.length; i++)
778 listeners[i].actionPerformed(ae);
782 * Calls {@link ChangeListener#stateChanged} on each {@link ChangeListener}
783 * in the button's listener list.
785 protected void fireStateChanged()
787 ChangeListener[] listeners = getChangeListeners();
789 for (int i = 0; i < listeners.length; i++)
790 listeners[i].stateChanged(changeEvent);
794 * Get the current keyboard mnemonic value. This value corresponds to a
795 * single key code (one of the {@link java.awt.event.KeyEvent} VK_*
796 * codes) and is used to activate the button when pressed in conjunction
797 * with the "mouseless modifier" of the button's look and feel class, and
798 * when focus is in one of the button's ancestors.
800 * @return The button's current keyboard mnemonic
802 public int getMnemonic()
804 ButtonModel mod = getModel();
806 return mod.getMnemonic();
811 * Set the current keyboard mnemonic value. This value corresponds to a
812 * single key code (one of the {@link java.awt.event.KeyEvent} VK_*
813 * codes) and is used to activate the button when pressed in conjunction
814 * with the "mouseless modifier" of the button's look and feel class, and
815 * when focus is in one of the button's ancestors.
817 * @param mne A new mnemonic to use for the button
819 public void setMnemonic(char mne)
821 setMnemonic((int) mne);
825 * Set the current keyboard mnemonic value. This value corresponds to a
826 * single key code (one of the {@link java.awt.event.KeyEvent} VK_*
827 * codes) and is used to activate the button when pressed in conjunction
828 * with the "mouseless modifier" of the button's look and feel class, and
829 * when focus is in one of the button's ancestors.
831 * @param mne A new mnemonic to use for the button
833 public void setMnemonic(int mne)
835 ButtonModel mod = getModel();
838 old = mod.getMnemonic();
843 mod.setMnemonic(mne);
845 if (text != null && !text.equals(""))
847 // Since lower case char = upper case char for
848 // mnemonic, we will convert both text and mnemonic
849 // to upper case before checking if mnemonic character occurs
850 // in the menu item text.
851 int upperCaseMne = Character.toUpperCase((char) mne);
852 String upperCaseText = text.toUpperCase();
853 setDisplayedMnemonicIndex(upperCaseText.indexOf(upperCaseMne));
856 firePropertyChange(MNEMONIC_CHANGED_PROPERTY, old, mne);
863 * Sets the button's mnemonic index. The mnemonic index is a hint to the
864 * look and feel class, suggesting which character in the button's label
865 * should be underlined when drawing the label. If the mnemonic index is
866 * -1, no mnemonic will be displayed.
868 * If no mnemonic index is set, the button will choose a mnemonic index
869 * by default, which will be the first occurrence of the mnemonic
870 * character in the button's text.
872 * @param index An offset into the "text" property of the button
873 * @throws IllegalArgumentException If <code>index</code> is not within the
874 * range of legal offsets for the "text" property of the button.
878 public void setDisplayedMnemonicIndex(int index)
880 if (index < -1 || (text != null && index >= text.length()))
881 throw new IllegalArgumentException();
883 mnemonicIndex = index;
887 * Get the button's mnemonic index, which is an offset into the button's
888 * "text" property. The character specified by this offset should be
889 * underlined when the look and feel class draws this button.
891 * @return An index into the button's "text" property
893 public int getDisplayedMnemonicIndex()
895 return mnemonicIndex;
900 * Set the "rolloverEnabled" property. When rollover is enabled, and the
901 * look and feel supports it, the button will change its icon to
902 * rolloverIcon, when the mouse passes over it.
904 * @param r Whether or not to enable rollover icon changes
906 public void setRolloverEnabled(boolean r)
908 if (rollOverEnabled != r)
911 firePropertyChange(ROLLOVER_ENABLED_CHANGED_PROPERTY, !r, r);
918 * Returns whether or not rollover icon changes are enabled on the
921 * @return The state of the "rolloverEnabled" property
923 public boolean isRolloverEnabled()
925 return rollOverEnabled;
929 * Set the value of the button's "selected" property. Selection is only
930 * meaningful for toggle-type buttons (check boxes, radio buttons).
932 * @param s New value for the property
934 public void setSelected(boolean s)
936 ButtonModel mod = getModel();
942 * Get the value of the button's "selected" property. Selection is only
943 * meaningful for toggle-type buttons (check boxes, radio buttons).
945 * @return The value of the property
947 public boolean isSelected()
949 ButtonModel mod = getModel();
951 return mod.isSelected();
956 * Enables or disables the button. A button will neither be selectable
957 * nor preform any actions unless it is enabled.
959 * @param b Whether or not to enable the button
961 public void setEnabled(boolean b)
963 // Do nothing if state does not change.
964 if (b == isEnabled())
968 ButtonModel mod = getModel();
974 * Set the horizontal alignment of the button's text and icon. The
975 * alignment is a numeric constant from {@link SwingConstants}. It must
976 * be one of: <code>RIGHT</code>, <code>LEFT</code>, <code>CENTER</code>,
977 * <code>LEADING</code> or <code>TRAILING</code>. The default is
978 * <code>RIGHT</code>.
980 * @return The current horizontal alignment
982 public int getHorizontalAlignment()
984 return horizontalAlignment;
988 * Set the horizontal alignment of the button's text and icon. The
989 * alignment is a numeric constant from {@link SwingConstants}. It must
990 * be one of: <code>RIGHT</code>, <code>LEFT</code>, <code>CENTER</code>,
991 * <code>LEADING</code> or <code>TRAILING</code>. The default is
992 * <code>RIGHT</code>.
994 * @param a The new horizontal alignment
995 * @throws IllegalArgumentException If alignment is not one of the legal
998 public void setHorizontalAlignment(int a)
1000 if (horizontalAlignment == a)
1003 int old = horizontalAlignment;
1004 horizontalAlignment = a;
1005 firePropertyChange(HORIZONTAL_ALIGNMENT_CHANGED_PROPERTY, old, a);
1011 * Get the horizontal position of the button's text relative to its
1012 * icon. The position is a numeric constant from {@link
1013 * SwingConstants}. It must be one of: <code>RIGHT</code>,
1014 * <code>LEFT</code>, <code>CENTER</code>, <code>LEADING</code> or
1015 * <code>TRAILING</code>. The default is <code>TRAILING</code>.
1017 * @return The current horizontal text position
1019 public int getHorizontalTextPosition()
1021 return horizontalTextPosition;
1025 * Set the horizontal position of the button's text relative to its
1026 * icon. The position is a numeric constant from {@link
1027 * SwingConstants}. It must be one of: <code>RIGHT</code>,
1028 * <code>LEFT</code>, <code>CENTER</code>, <code>LEADING</code> or
1029 * <code>TRAILING</code>. The default is <code>TRAILING</code>.
1031 * @param t The new horizontal text position
1032 * @throws IllegalArgumentException If position is not one of the legal
1035 public void setHorizontalTextPosition(int t)
1037 if (horizontalTextPosition == t)
1040 int old = horizontalTextPosition;
1041 horizontalTextPosition = t;
1042 firePropertyChange(HORIZONTAL_TEXT_POSITION_CHANGED_PROPERTY, old, t);
1048 * Get the vertical alignment of the button's text and icon. The
1049 * alignment is a numeric constant from {@link SwingConstants}. It must
1050 * be one of: <code>CENTER</code>, <code>TOP</code>, or
1051 * <code>BOTTOM</code>. The default is <code>CENTER</code>.
1053 * @return The current vertical alignment
1055 public int getVerticalAlignment()
1057 return verticalAlignment;
1061 * Set the vertical alignment of the button's text and icon. The
1062 * alignment is a numeric constant from {@link SwingConstants}. It must
1063 * be one of: <code>CENTER</code>, <code>TOP</code>, or
1064 * <code>BOTTOM</code>. The default is <code>CENTER</code>.
1066 * @param a The new vertical alignment
1067 * @throws IllegalArgumentException If alignment is not one of the legal
1070 public void setVerticalAlignment(int a)
1072 if (verticalAlignment == a)
1075 int old = verticalAlignment;
1076 verticalAlignment = a;
1077 firePropertyChange(VERTICAL_ALIGNMENT_CHANGED_PROPERTY, old, a);
1083 * Get the vertical position of the button's text relative to its
1084 * icon. The alignment is a numeric constant from {@link
1085 * SwingConstants}. It must be one of: <code>CENTER</code>,
1086 * <code>TOP</code>, or <code>BOTTOM</code>. The default is
1087 * <code>CENTER</code>.
1089 * @return The current vertical position
1091 public int getVerticalTextPosition()
1093 return verticalTextPosition;
1097 * Set the vertical position of the button's text relative to its
1098 * icon. The alignment is a numeric constant from {@link
1099 * SwingConstants}. It must be one of: <code>CENTER</code>,
1100 * <code>TOP</code>, or <code>BOTTOM</code>. The default is
1101 * <code>CENTER</code>.
1103 * @param t The new vertical position
1104 * @throws IllegalArgumentException If position is not one of the legal
1107 public void setVerticalTextPosition(int t)
1109 if (verticalTextPosition == t)
1112 int old = verticalTextPosition;
1113 verticalTextPosition = t;
1114 firePropertyChange(VERTICAL_TEXT_POSITION_CHANGED_PROPERTY, old, t);
1120 * Set the value of the "borderPainted" property. If set to
1121 * <code>false</code>, the button's look and feel class should not paint
1122 * a border for the button. The default is <code>true</code>.
1124 * @return The current value of the property.
1126 public boolean isBorderPainted()
1128 return borderPainted;
1132 * Set the value of the "borderPainted" property. If set to
1133 * <code>false</code>, the button's look and feel class should not paint
1134 * a border for the button. The default is <code>true</code>.
1136 * @param b The new value of the property.
1138 public void setBorderPainted(boolean b)
1140 if (borderPainted == b)
1143 boolean old = borderPainted;
1145 firePropertyChange(BORDER_PAINTED_CHANGED_PROPERTY, old, b);
1151 * Get the value of the "action" property.
1153 * @return The current value of the "action" property
1155 public Action getAction()
1161 * <p>Set the button's "action" property, subscribing the new action to the
1162 * button, as an ActionListener, if it is not already subscribed. The old
1163 * Action, if it exists, is unsubscribed, and the button is unsubscribed
1164 * from the old Action if it was previously subscribed as a
1165 * PropertyChangeListener.</p>
1167 * <p>This method also configures several of the button's properties from
1168 * the Action, by calling {@link #configurePropertiesFromAction}, and
1169 * subscribes the button to the Action as a PropertyChangeListener.
1170 * Subsequent changes to the Action will thus reconfigure the button
1171 * automatically.</p>
1173 * @param a The new value of the "action" property
1175 public void setAction(Action a)
1179 action.removePropertyChangeListener(actionPropertyChangeListener);
1180 removeActionListener(action);
1181 if (actionPropertyChangeListener != null)
1183 action.removePropertyChangeListener(actionPropertyChangeListener);
1184 actionPropertyChangeListener = null;
1188 Action old = action;
1190 configurePropertiesFromAction(action);
1193 actionPropertyChangeListener = createActionPropertyChangeListener(a);
1194 action.addPropertyChangeListener(actionPropertyChangeListener);
1195 addActionListener(action);
1200 * Return the button's default "icon" property.
1202 * @return The current default icon
1204 public Icon getIcon()
1206 return default_icon;
1210 * Set the button's default "icon" property. This icon is used as a basis
1211 * for the pressed and disabled icons, if none are explicitly set.
1213 * @param i The new default icon
1215 public void setIcon(Icon i)
1217 if (default_icon == i)
1220 Icon old = default_icon;
1222 firePropertyChange(ICON_CHANGED_PROPERTY, old, i);
1228 * Return the button's "text" property. This property is synonymous with
1229 * the "label" property.
1231 * @return The current "text" property
1233 public String getText()
1239 * Set the button's "label" property. This property is synonymous with the
1242 * @param label The new "label" property
1244 * @deprecated use <code>setText(text)</code>
1246 public void setLabel(String label)
1252 * Return the button's "label" property. This property is synonymous with
1253 * the "text" property.
1255 * @return The current "label" property
1257 * @deprecated use <code>getText()</code>
1259 public String getLabel()
1265 * Set the button's "text" property. This property is synonymous with the
1268 * @param t The new "text" property
1270 public void setText(String t)
1277 firePropertyChange(TEXT_CHANGED_PROPERTY, old, t);
1283 * Set the value of the {@link #iconTextGap} property.
1285 * @param i The new value of the property
1287 public void setIconTextGap(int i)
1289 if (iconTextGap == i)
1292 int old = iconTextGap;
1300 * Get the value of the {@link #iconTextGap} property.
1302 * @return The current value of the property
1304 public int getIconTextGap()
1310 * Return the button's "margin" property, which is an {@link Insets} object
1311 * describing the distance between the button's border and its text and
1314 * @return The current "margin" property
1316 public Insets getMargin()
1322 * Set the button's "margin" property, which is an {@link Insets} object
1323 * describing the distance between the button's border and its text and
1326 * @param m The new "margin" property
1328 public void setMargin(Insets m)
1333 Insets old = margin;
1335 firePropertyChange(MARGIN_CHANGED_PROPERTY, old, m);
1341 * Return the button's "pressedIcon" property. The look and feel class
1342 * should paint this icon when the "pressed" property of the button's
1343 * {@link ButtonModel} is <code>true</code>. This property may be
1344 * <code>null</code>, in which case the default icon is used.
1346 * @return The current "pressedIcon" property
1348 public Icon getPressedIcon()
1350 return pressed_icon;
1354 * Set the button's "pressedIcon" property. The look and feel class
1355 * should paint this icon when the "pressed" property of the button's
1356 * {@link ButtonModel} is <code>true</code>. This property may be
1357 * <code>null</code>, in which case the default icon is used.
1359 * @param pressedIcon The new "pressedIcon" property
1361 public void setPressedIcon(Icon pressedIcon)
1363 if (pressed_icon == pressedIcon)
1366 Icon old = pressed_icon;
1367 pressed_icon = pressedIcon;
1368 firePropertyChange(PRESSED_ICON_CHANGED_PROPERTY, old, pressed_icon);
1374 * Return the button's "disabledIcon" property. The look and feel class
1375 * should paint this icon when the "enabled" property of the button's
1376 * {@link ButtonModel} is <code>false</code>. This property may be
1377 * <code>null</code>, in which case an icon is constructed, based on the
1380 * @return The current "disabledIcon" property
1382 public Icon getDisabledIcon()
1384 if (disabeldIcon == null && default_icon instanceof ImageIcon)
1386 Image iconImage = ((ImageIcon) default_icon).getImage();
1387 Image grayImage = GrayFilter.createDisabledImage(iconImage);
1388 disabeldIcon = new ImageIcon(grayImage);
1391 return disabeldIcon;
1395 * Set the button's "disabledIcon" property. The look and feel class should
1396 * paint this icon when the "enabled" property of the button's {@link
1397 * ButtonModel} is <code>false</code>. This property may be
1398 * <code>null</code>, in which case an icon is constructed, based on the
1401 * @param d The new "disabledIcon" property
1403 public void setDisabledIcon(Icon d)
1411 * Return the button's "paintFocus" property. This property controls
1412 * whether or not the look and feel class will paint a special indicator
1413 * of focus state for the button. If it is false, the button still paints
1414 * when focused, but no special decoration is painted to indicate the
1415 * presence of focus.
1417 * @return The current "paintFocus" property
1419 public boolean isFocusPainted()
1421 return focusPainted;
1425 * Set the button's "paintFocus" property. This property controls whether
1426 * or not the look and feel class will paint a special indicator of focus
1427 * state for the button. If it is false, the button still paints when
1428 * focused, but no special decoration is painted to indicate the presence
1431 * @param p The new "paintFocus" property
1433 public void setFocusPainted(boolean p)
1435 if (focusPainted == p)
1438 boolean old = focusPainted;
1440 firePropertyChange(FOCUS_PAINTED_CHANGED_PROPERTY, old, p);
1446 * Verifies that a particular key is one of the valid constants used for
1447 * describing horizontal alignment and positioning. The valid constants
1448 * are the following members of {@link SwingConstants}:
1449 * <code>RIGHT</code>, <code>LEFT</code>, <code>CENTER</code>,
1450 * <code>LEADING</code> or <code>TRAILING</code>.
1452 * @param key The key to check
1453 * @param exception A message to include in an IllegalArgumentException
1455 * @return the value of key
1457 * @throws IllegalArgumentException If key is not one of the valid constants
1459 * @see #setHorizontalTextPosition(int)
1460 * @see #setHorizontalAlignment(int)
1462 protected int checkHorizontalKey(int key, String exception)
1466 case SwingConstants.RIGHT:
1467 case SwingConstants.LEFT:
1468 case SwingConstants.CENTER:
1469 case SwingConstants.LEADING:
1470 case SwingConstants.TRAILING:
1473 throw new IllegalArgumentException(exception);
1479 * Verifies that a particular key is one of the valid constants used for
1480 * describing vertical alignment and positioning. The valid constants are
1481 * the following members of {@link SwingConstants}: <code>TOP</code>,
1482 * <code>BOTTOM</code> or <code>CENTER</code>.
1484 * @param key The key to check
1485 * @param exception A message to include in an IllegalArgumentException
1487 * @return the value of key
1489 * @throws IllegalArgumentException If key is not one of the valid constants
1491 * @see #setVerticalTextPosition(int)
1492 * @see #setVerticalAlignment(int)
1494 protected int checkVerticalKey(int key, String exception)
1498 case SwingConstants.TOP:
1499 case SwingConstants.BOTTOM:
1500 case SwingConstants.CENTER:
1503 throw new IllegalArgumentException(exception);
1509 * Configure various properties of the button by reading properties
1510 * of an {@link Action}. The mapping of properties is as follows:
1514 * <tr><th>Action keyed property</th> <th>AbstractButton property</th></tr>
1516 * <tr><td>NAME </td> <td>text </td></tr>
1517 * <tr><td>SMALL_ICON </td> <td>icon </td></tr>
1518 * <tr><td>SHORT_DESCRIPTION </td> <td>toolTipText </td></tr>
1519 * <tr><td>MNEMONIC_KEY </td> <td>mnemonic </td></tr>
1520 * <tr><td>ACTION_COMMAND_KEY </td> <td>actionCommand </td></tr>
1524 * <p>In addition, this method always sets the button's "enabled" property to
1525 * the value of the Action's "enabled" property.</p>
1527 * <p>If the provided Action is <code>null</code>, the text, icon, and
1528 * toolTipText properties of the button are set to <code>null</code>, and
1529 * the "enabled" property is set to <code>true</code>; the mnemonic and
1530 * actionCommand properties are unchanged.</p>
1532 * @param a An Action to configure the button from
1534 protected void configurePropertiesFromAction(Action a)
1541 setToolTipText(null);
1545 setText((String) (a.getValue(Action.NAME)));
1546 setIcon((Icon) (a.getValue(Action.SMALL_ICON)));
1547 setEnabled(a.isEnabled());
1548 setToolTipText((String) (a.getValue(Action.SHORT_DESCRIPTION)));
1549 if (a.getValue(Action.MNEMONIC_KEY) != null)
1550 setMnemonic(((Integer) (a.getValue(Action.MNEMONIC_KEY))).intValue());
1551 String actionCommand = (String) (a.getValue(Action.ACTION_COMMAND_KEY));
1553 // Set actionCommand to button's text by default if it is not specified
1554 if (actionCommand != null)
1555 setActionCommand((String) (a.getValue(Action.ACTION_COMMAND_KEY)));
1557 setActionCommand(getText());
1562 * <p>A factory method which should return an {@link ActionListener} that
1563 * propagates events from the button's {@link ButtonModel} to any of the
1564 * button's ActionListeners. By default, this is an inner class which
1565 * calls {@link AbstractButton#fireActionPerformed} with a modified copy
1566 * of the incoming model {@link ActionEvent}.</p>
1568 * <p>The button calls this method during construction, stores the
1569 * resulting ActionListener in its <code>actionListener</code> member
1570 * field, and subscribes it to the button's model. If the button's model
1571 * is changed, this listener is unsubscribed from the old model and
1572 * subscribed to the new one.</p>
1574 * @return A new ActionListener
1576 protected ActionListener createActionListener()
1578 return new ActionListener()
1580 public void actionPerformed(ActionEvent e)
1582 AbstractButton.this.fireActionPerformed(e);
1588 * <p>A factory method which should return a {@link PropertyChangeListener}
1589 * that accepts changes to the specified {@link Action} and reconfigure
1590 * the {@link AbstractButton}, by default using the {@link
1591 * #configurePropertiesFromAction} method.</p>
1593 * <p>The button calls this method whenever a new Action is assigned to
1594 * the button's "action" property, via {@link #setAction}, and stores the
1595 * resulting PropertyChangeListener in its
1596 * <code>actionPropertyChangeListener</code> member field. The button
1597 * then subscribes the listener to the button's new action. If the
1598 * button's action is changed subsequently, the listener is unsubscribed
1599 * from the old action and subscribed to the new one.</p>
1601 * @param a The Action which will be listened to, and which should be
1602 * the same as the source of any PropertyChangeEvents received by the
1603 * new listener returned from this method.
1605 * @return A new PropertyChangeListener
1607 protected PropertyChangeListener createActionPropertyChangeListener(Action a)
1609 return new PropertyChangeListener()
1611 public void propertyChange(PropertyChangeEvent e)
1613 Action act = (Action) (e.getSource());
1614 if (e.getPropertyName().equals("enabled"))
1615 setEnabled(act.isEnabled());
1616 else if (e.getPropertyName().equals(Action.NAME))
1617 setText((String) (act.getValue(Action.NAME)));
1618 else if (e.getPropertyName().equals(Action.SMALL_ICON))
1619 setIcon((Icon) (act.getValue(Action.SMALL_ICON)));
1620 else if (e.getPropertyName().equals(Action.SHORT_DESCRIPTION))
1621 setToolTipText((String) (act.getValue(Action.SHORT_DESCRIPTION)));
1622 else if (e.getPropertyName().equals(Action.MNEMONIC_KEY))
1623 if (act.getValue(Action.MNEMONIC_KEY) != null)
1624 setMnemonic(((Integer) (act.getValue(Action.MNEMONIC_KEY)))
1626 else if (e.getPropertyName().equals(Action.ACTION_COMMAND_KEY))
1627 setActionCommand((String) (act.getValue(Action.ACTION_COMMAND_KEY)));
1633 * <p>Factory method which creates a {@link ChangeListener}, used to
1634 * subscribe to ChangeEvents from the button's model. Subclasses of
1635 * AbstractButton may wish to override the listener used to subscribe to
1636 * such ChangeEvents. By default, the listener just propagates the
1637 * {@link ChangeEvent} to the button's ChangeListeners, via the {@link
1638 * AbstractButton#fireStateChanged} method.</p>
1640 * <p>The button calls this method during construction, stores the
1641 * resulting ChangeListener in its <code>changeListener</code> member
1642 * field, and subscribes it to the button's model. If the button's model
1643 * is changed, this listener is unsubscribed from the old model and
1644 * subscribed to the new one.</p>
1646 * @return The new ChangeListener
1648 protected ChangeListener createChangeListener()
1650 return new ButtonChangeListener();
1654 * <p>Factory method which creates a {@link ItemListener}, used to
1655 * subscribe to ItemEvents from the button's model. Subclasses of
1656 * AbstractButton may wish to override the listener used to subscribe to
1657 * such ItemEvents. By default, the listener just propagates the
1658 * {@link ItemEvent} to the button's ItemListeners, via the {@link
1659 * AbstractButton#fireItemStateChanged} method.</p>
1661 * <p>The button calls this method during construction, stores the
1662 * resulting ItemListener in its <code>changeListener</code> member
1663 * field, and subscribes it to the button's model. If the button's model
1664 * is changed, this listener is unsubscribed from the old model and
1665 * subscribed to the new one.</p>
1667 * <p>Note that ItemEvents are only generated from the button's model
1668 * when the model's <em>selected</em> property changes. If you want to
1669 * subscribe to other properties of the model, you must subscribe to
1672 * @return The new ItemListener
1674 protected ItemListener createItemListener()
1676 return new ItemListener()
1678 public void itemStateChanged(ItemEvent e)
1680 AbstractButton.this.fireItemStateChanged(e);
1686 * Programmatically perform a "click" on the button: arming, pressing,
1687 * waiting, un-pressing, and disarming the model.
1689 public void doClick()
1695 * Programmatically perform a "click" on the button: arming, pressing,
1696 * waiting, un-pressing, and disarming the model.
1698 * @param pressTime The number of milliseconds to wait in the pressed state
1700 public void doClick(int pressTime)
1702 ButtonModel mod = getModel();
1706 mod.setPressed(true);
1709 java.lang.Thread.sleep(pressTime);
1711 catch (java.lang.InterruptedException e)
1713 // probably harmless
1715 mod.setPressed(false);
1716 mod.setArmed(false);
1721 * Return the button's disabled selected icon. The look and feel class
1722 * should paint this icon when the "enabled" property of the button's model
1723 * is <code>false</code> and its "selected" property is
1724 * <code>true</code>. This icon can be <code>null</code>, in which case
1725 * it is synthesized from the button's selected icon.
1727 * @return The current disabled selected icon
1729 public Icon getDisabledSelectedIcon()
1731 return disabledSelectedIcon;
1735 * Set the button's disabled selected icon. The look and feel class
1736 * should paint this icon when the "enabled" property of the button's model
1737 * is <code>false</code> and its "selected" property is
1738 * <code>true</code>. This icon can be <code>null</code>, in which case
1739 * it is synthesized from the button's selected icon.
1741 * @param icon The new disabled selected icon
1743 public void setDisabledSelectedIcon(Icon icon)
1745 if (disabledSelectedIcon == icon)
1748 Icon old = disabledSelectedIcon;
1749 disabledSelectedIcon = icon;
1750 firePropertyChange(DISABLED_SELECTED_ICON_CHANGED_PROPERTY, old, icon);
1756 * Return the button's rollover icon. The look and feel class should
1757 * paint this icon when the "rolloverEnabled" property of the button is
1758 * <code>true</code> and the mouse rolls over the button.
1760 * @return The current rollover icon
1762 public Icon getRolloverIcon()
1764 return rolloverIcon;
1768 * Set the button's rollover icon. The look and feel class should
1769 * paint this icon when the "rolloverEnabled" property of the button is
1770 * <code>true</code> and the mouse rolls over the button.
1772 * @param r The new rollover icon
1774 public void setRolloverIcon(Icon r)
1776 if (rolloverIcon == r)
1779 Icon old = rolloverIcon;
1781 firePropertyChange(ROLLOVER_ICON_CHANGED_PROPERTY, old, rolloverIcon);
1787 * Return the button's rollover selected icon. The look and feel class
1788 * should paint this icon when the "rolloverEnabled" property of the button
1789 * is <code>true</code>, the "selected" property of the button's model is
1790 * <code>true</code>, and the mouse rolls over the button.
1792 * @return The current rollover selected icon
1794 public Icon getRolloverSelectedIcon()
1796 return rolloverSelectedIcon;
1800 * Set the button's rollover selected icon. The look and feel class
1801 * should paint this icon when the "rolloverEnabled" property of the button
1802 * is <code>true</code>, the "selected" property of the button's model is
1803 * <code>true</code>, and the mouse rolls over the button.
1805 * @param r The new rollover selected icon
1807 public void setRolloverSelectedIcon(Icon r)
1809 if (rolloverSelectedIcon == r)
1812 Icon old = rolloverSelectedIcon;
1813 rolloverSelectedIcon = r;
1814 firePropertyChange(ROLLOVER_SELECTED_ICON_CHANGED_PROPERTY, old, r);
1820 * Return the button's selected icon. The look and feel class should
1821 * paint this icon when the "selected" property of the button's model is
1822 * <code>true</code>, and either the "rolloverEnabled" property of the
1823 * button is <code>false</code> or the mouse is not currently rolled
1826 * @return The current selected icon
1828 public Icon getSelectedIcon()
1830 return selectedIcon;
1834 * Set the button's selected icon. The look and feel class should
1835 * paint this icon when the "selected" property of the button's model is
1836 * <code>true</code>, and either the "rolloverEnabled" property of the
1837 * button is <code>false</code> or the mouse is not currently rolled
1840 * @param s The new selected icon
1842 public void setSelectedIcon(Icon s)
1844 if (selectedIcon == s)
1847 Icon old = selectedIcon;
1849 firePropertyChange(SELECTED_ICON_CHANGED_PROPERTY, old, s);
1855 * Returns an single-element array containing the "text" property of the
1856 * button if the "selected" property of the button's model is
1857 * <code>true</code>, otherwise returns <code>null</code>.
1859 * @return The button's "selected object" array
1861 public Object[] getSelectedObjects()
1865 Object[] objs = new Object[1];
1866 objs[0] = getText();
1876 * Called when image data becomes available for one of the button's icons.
1878 * @param img The image being updated
1879 * @param infoflags One of the constant codes in {@link ImageObserver} used
1880 * to describe updated portions of an image.
1881 * @param x X coordinate of the region being updated
1882 * @param y Y coordinate of the region being updated
1883 * @param w Width of the region beign updated
1884 * @param h Height of the region being updated
1886 * @return <code>true</code> if img is equal to the button's current icon,
1887 * otherwise <code>false</code>
1889 public boolean imageUpdate(Image img, int infoflags, int x, int y, int w,
1892 return current_icon == img;
1896 * Returns the value of the button's "contentAreaFilled" property. This
1897 * property indicates whether the area surrounding the text and icon of
1898 * the button should be filled by the look and feel class. If this
1899 * property is <code>false</code>, the look and feel class should leave
1900 * the content area transparent.
1902 * @return The current value of the "contentAreaFilled" property
1904 public boolean isContentAreaFilled()
1906 return contentAreaFilled;
1910 * Sets the value of the button's "contentAreaFilled" property. This
1911 * property indicates whether the area surrounding the text and icon of
1912 * the button should be filled by the look and feel class. If this
1913 * property is <code>false</code>, the look and feel class should leave
1914 * the content area transparent.
1916 * @param b The new value of the "contentAreaFilled" property
1918 public void setContentAreaFilled(boolean b)
1920 if (contentAreaFilled == b)
1923 boolean old = contentAreaFilled;
1924 contentAreaFilled = b;
1925 firePropertyChange(CONTENT_AREA_FILLED_CHANGED_PROPERTY, old, b);
1926 // The JDK sets the opaque property to the value of the contentAreaFilled
1927 // property, so should we do.
1932 * Paints the button's border, if the button's "borderPainted" property is
1933 * <code>true</code>, by out calling to the button's look and feel class.
1935 * @param g The graphics context used to paint the border
1937 protected void paintBorder(Graphics g)
1939 if (isBorderPainted())
1940 super.paintBorder(g);
1944 * Returns a string, used only for debugging, which identifies or somehow
1945 * represents this button. The exact value is implementation-defined.
1947 * @return A string representation of the button
1949 protected String paramString()
1951 StringBuffer sb = new StringBuffer();
1952 sb.append(super.paramString());
1953 sb.append(",defaultIcon=");
1954 if (getIcon() != null)
1955 sb.append(getIcon());
1956 sb.append(",disabledIcon=");
1957 if (getDisabledIcon() != null)
1958 sb.append(getDisabledIcon());
1959 sb.append(",disabledSelectedIcon=");
1960 if (getDisabledSelectedIcon() != null)
1961 sb.append(getDisabledSelectedIcon());
1962 sb.append(",margin=");
1963 if (getMargin() != null)
1964 sb.append(getMargin());
1965 sb.append(",paintBorder=").append(isBorderPainted());
1966 sb.append(",paintFocus=").append(isFocusPainted());
1967 sb.append(",pressedIcon=");
1968 if (getPressedIcon() != null)
1969 sb.append(getPressedIcon());
1970 sb.append(",rolloverEnabled=").append(isRolloverEnabled());
1971 sb.append(",rolloverIcon=");
1972 if (getRolloverIcon() != null)
1973 sb.append(getRolloverIcon());
1974 sb.append(",rolloverSelected=");
1975 if (getRolloverSelectedIcon() != null)
1976 sb.append(getRolloverSelectedIcon());
1977 sb.append(",selectedIcon=");
1978 if (getSelectedIcon() != null)
1979 sb.append(getSelectedIcon());
1980 sb.append(",text=");
1981 if (getText() != null)
1982 sb.append(getText());
1983 return sb.toString();
1987 * Set the "UI" property of the button, which is a look and feel class
1988 * responsible for handling the button's input events and painting it.
1990 * @param ui The new "UI" property
1992 public void setUI(ButtonUI ui)
1998 * Set the "UI" property of the button, which is a look and feel class
1999 * responsible for handling the button's input events and painting it.
2001 * @return The current "UI" property
2003 public ButtonUI getUI()
2005 return (ButtonUI) ui;
2009 * Set the "UI" property to a class constructed, via the {@link
2010 * UIManager}, from the current look and feel. This should be overridden
2011 * for each subclass of AbstractButton, to retrieve a suitable {@link
2012 * ButtonUI} look and feel class.
2014 public void updateUI()
2016 // TODO: What to do here?
2020 * Returns the current time in milliseconds in which clicks gets coalesced
2021 * into a single <code>ActionEvent</code>.
2023 * @return the time in milliseconds
2027 public long getMultiClickThreshhold()
2029 return multiClickThreshhold;
2033 * Sets the time in milliseconds in which clicks gets coalesced into a single
2034 * <code>ActionEvent</code>.
2036 * @param threshhold the time in milliseconds
2040 public void setMultiClickThreshhold(long threshhold)
2043 throw new IllegalArgumentException();
2045 multiClickThreshhold = threshhold;