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