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