GNU Classpath (0.18) | ||
Frames | No Frames |
1: /* DefaultButtonModel.java -- 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: 39: package javax.swing; 40: 41: import java.awt.ItemSelectable; 42: import java.awt.event.ActionEvent; 43: import java.awt.event.ActionListener; 44: import java.awt.event.ItemEvent; 45: import java.awt.event.ItemListener; 46: import java.awt.event.KeyEvent; 47: import java.io.Serializable; 48: import java.util.EventListener; 49: 50: import javax.swing.event.ChangeEvent; 51: import javax.swing.event.ChangeListener; 52: import javax.swing.event.EventListenerList; 53: 54: /** 55: * The default implementation of {@link ButtonModel}. 56: * The purpose of this class is to model the dynamic state of an abstract 57: * button. The concrete button type holding this state may be a a "toggle" 58: * button (checkbox, radio button) or a "push" button (menu button, button). 59: * If the model is disabled, only the "selected" property can be changed. An 60: * attempt to change the "armed", "rollover" or "pressed" properties while 61: * the model is disabled will be blocked. Any successful (non-blocked) change 62: * to the model's properties will trigger the firing of a ChangeEvent. Any 63: * change to the "selected" property will trigger the firing of an ItemEvent 64: * in addition to ChangeEvent. This is true whether the model is enabled or 65: * not. One other state change is special: the transition from "enabled, 66: * armed and pressd" to "enabled, armed and not-pressed". This is considered 67: * the "trailing edge" of a successful mouse click, and therefore fires an 68: * ActionEvent in addition to a ChangeEvent. In all other respects this class 69: * is just a container of boolean flags. 70: * 71: * @author Graydon Hoare (graydon_at_redhat.com) 72: */ 73: public class DefaultButtonModel implements ButtonModel, Serializable 74: { 75: /** DOCUMENT ME! */ 76: private static final long serialVersionUID = -5342609566534980231L; 77: 78: /** 79: * Indicates that the button is <em>partially</em> committed to being 80: * pressed, but not entirely. This usually happens when a user has pressed 81: * but not yet released the mouse button. 82: */ 83: public static final int ARMED = 1; 84: 85: /** 86: * State constant indicating that the button is enabled. Buttons cannot be 87: * pressed or selected unless they are enabled. 88: */ 89: public static final int ENABLED = 8; 90: 91: /** 92: * State constant indicating that the user is holding down the button. When 93: * this transitions from true to false, an ActionEvent may be fired, 94: * depending on the value of the "armed" property. 95: */ 96: public static final int PRESSED = 4; 97: 98: /** 99: * State constant indicating that the mouse is currently positioned over the 100: * button. 101: */ 102: public static final int ROLLOVER = 16; 103: 104: /** 105: * State constant indicating that the button is selected. This constant is 106: * only meaningful for toggle-type buttons (radio buttons, checkboxes). 107: */ 108: public static final int SELECTED = 2; 109: 110: /** 111: * Represents the "state properties" (armed, enabled, pressed, rollover and 112: * selected) by a bitwise combination of integer constants. 113: */ 114: protected int stateMask = ENABLED; 115: 116: /** 117: * List of ItemListeners, ChangeListeners, and ActionListeners registered on 118: * this model. 119: */ 120: protected EventListenerList listenerList = new EventListenerList(); 121: 122: /** The single ChangeEvent this model (re)uses to call its ChangeListeners. */ 123: protected ChangeEvent changeEvent = new ChangeEvent(this); 124: 125: /** 126: * The group this model belongs to. Only one button in a group may be 127: * selected at any given time. 128: */ 129: protected ButtonGroup group; 130: 131: /** 132: * The key code (one of {@link java.awt.event.KeyEvent} VK_) used to press 133: * this button via a keyboard interface. 134: */ 135: protected int mnemonic = KeyEvent.VK_UNDEFINED; 136: 137: /** 138: * The string used as the "command" property of any ActionEvent this model 139: * sends. 140: */ 141: protected String actionCommand; 142: 143: /** 144: * Creates a new DefaultButtonModel object. 145: */ 146: public DefaultButtonModel() 147: { 148: } 149: 150: /** 151: * Return <code>null</code>. Use {@link AbstractButton} if you wish to 152: * interface with a button via an {@link ItemSelectable} interface. 153: * 154: * @return <code>null</code> 155: */ 156: public Object[] getSelectedObjects() 157: { 158: return null; 159: } 160: 161: /** 162: * Returns a specified class of listeners. 163: * 164: * @param listenerType the type of listener to return 165: * 166: * @return array of listeners 167: */ 168: public EventListener[] getListeners(Class listenerType) 169: { 170: return listenerList.getListeners(listenerType); 171: } 172: 173: /** 174: * Add an ActionListener to the model. Usually only called to subscribe an 175: * AbstractButton's listener to the model. 176: * 177: * @param l The listener to add 178: */ 179: public void addActionListener(ActionListener l) 180: { 181: listenerList.add(ActionListener.class, l); 182: } 183: 184: /** 185: * Remove an ActionListener to the model. Usually only called to unsubscribe 186: * an AbstractButton's listener to the model. 187: * 188: * @param l The listener to remove 189: */ 190: public void removeActionListener(ActionListener l) 191: { 192: listenerList.remove(ActionListener.class, l); 193: } 194: 195: /** 196: * Returns all registered <code>ActionListener</code> objects. 197: * 198: * @return array of <code>ActionListener</code> objects 199: */ 200: public ActionListener[] getActionListeners() 201: { 202: return (ActionListener[]) listenerList.getListeners(ActionListener.class); 203: } 204: 205: /** 206: * Add an ItemListener to the model. Usually only called to subscribe an 207: * AbstractButton's listener to the model. 208: * 209: * @param l The listener to add 210: */ 211: public void addItemListener(ItemListener l) 212: { 213: listenerList.add(ItemListener.class, l); 214: } 215: 216: /** 217: * Remove an ItemListener to the model. Usually only called to unsubscribe 218: * an AbstractButton's listener to the model. 219: * 220: * @param l The listener to remove 221: */ 222: public void removeItemListener(ItemListener l) 223: { 224: listenerList.remove(ItemListener.class, l); 225: } 226: 227: /** 228: * Returns all registered <code>ItemListener</code> objects. 229: * 230: * @return array of <code>ItemListener</code> objects 231: */ 232: public ItemListener[] getItemListeners() 233: { 234: return (ItemListener[]) listenerList.getListeners(ItemListener.class); 235: } 236: 237: /** 238: * Add a ChangeListener to the model. Usually only called to subscribe an 239: * AbstractButton's listener to the model. 240: * 241: * @param l The listener to add 242: */ 243: public void addChangeListener(ChangeListener l) 244: { 245: listenerList.add(ChangeListener.class, l); 246: } 247: 248: /** 249: * Remove a ChangeListener to the model. Usually only called to unsubscribe 250: * an AbstractButton's listener to the model. 251: * 252: * @param l The listener to remove 253: */ 254: public void removeChangeListener(ChangeListener l) 255: { 256: listenerList.remove(ChangeListener.class, l); 257: } 258: 259: /** 260: * Returns all registered <code>ChangeListener</code> objects. 261: * 262: * @return array of <code>ChangeListener</code> objects 263: */ 264: public ChangeListener[] getChangeListeners() 265: { 266: return (ChangeListener[]) listenerList.getListeners(ChangeListener.class); 267: } 268: 269: /** 270: * Inform each ItemListener in the {@link #listenerList} that an ItemEvent 271: * has occurred. This happens in response to any change to the {@link 272: * #stateMask} field. 273: * 274: * @param e The ItemEvent to fire 275: */ 276: protected void fireItemStateChanged(ItemEvent e) 277: { 278: ItemListener[] ll = getItemListeners(); 279: 280: for (int i = 0; i < ll.length; i++) 281: ll[i].itemStateChanged(e); 282: } 283: 284: /** 285: * Inform each ActionListener in the {@link #listenerList} that an 286: * ActionEvent has occurred. This happens in response to the any change to 287: * the {@link #stateMask} field which makes the enabled, armed and pressed 288: * properties all simultaneously <code>true</code>. 289: * 290: * @param e The ActionEvent to fire 291: */ 292: protected void fireActionPerformed(ActionEvent e) 293: { 294: ActionListener[] ll = getActionListeners(); 295: 296: for (int i = 0; i < ll.length; i++) 297: ll[i].actionPerformed(e); 298: } 299: 300: /** 301: * Inform each ChangeListener in the {@link #listenerList} that a ChangeEvent 302: * has occurred. This happens in response to the any change to a property 303: * of the model. 304: */ 305: protected void fireStateChanged() 306: { 307: ChangeListener[] ll = getChangeListeners(); 308: 309: for (int i = 0; i < ll.length; i++) 310: ll[i].stateChanged(changeEvent); 311: } 312: 313: /** 314: * Get the value of the model's "armed" property. 315: * 316: * @return The current "armed" property 317: */ 318: public boolean isArmed() 319: { 320: return (stateMask & ARMED) == ARMED; 321: } 322: 323: /** 324: * Set the value of the model's "armed" property. 325: * 326: * @param a The new "armed" property 327: */ 328: public void setArmed(boolean a) 329: { 330: // if this call does not represent a CHANGE in state, then return 331: if ((a && isArmed()) || (!a && !isArmed())) 332: return; 333: 334: // cannot change ARMED state unless button is enabled 335: if (!isEnabled()) 336: return; 337: 338: // make the change 339: if (a) 340: stateMask = stateMask | ARMED; 341: else 342: stateMask = stateMask & (~ARMED); 343: 344: // notify interested ChangeListeners 345: fireStateChanged(); 346: } 347: 348: /** 349: * Get the value of the model's "enabled" property. 350: * 351: * @return The current "enabled" property. 352: */ 353: public boolean isEnabled() 354: { 355: return (stateMask & ENABLED) == ENABLED; 356: } 357: 358: /** 359: * Set the value of the model's "enabled" property. 360: * 361: * @param e The new "enabled" property 362: */ 363: public void setEnabled(boolean e) 364: { 365: // if this call does not represent a CHANGE in state, then return 366: if ((e && isEnabled()) || (!e && !isEnabled())) 367: return; 368: 369: // make the change 370: if (e) 371: stateMask = stateMask | ENABLED; 372: else 373: stateMask = stateMask & (~ENABLED); 374: 375: // notify interested ChangeListeners 376: fireStateChanged(); 377: } 378: 379: /** 380: * Set the value of the model's "pressed" property. 381: * 382: * @param p The new "pressed" property 383: */ 384: public void setPressed(boolean p) 385: { 386: // if this call does not represent a CHANGE in state, then return 387: if ((p && isPressed()) || (!p && !isPressed())) 388: return; 389: 390: // cannot changed PRESSED state unless button is enabled 391: if (!isEnabled()) 392: return; 393: 394: // make the change 395: if (p) 396: stateMask = stateMask | PRESSED; 397: else 398: stateMask = stateMask & (~PRESSED); 399: 400: // if button is armed and was released, fire action event 401: if (!p && isArmed()) 402: fireActionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, 403: actionCommand)); 404: 405: // notify interested ChangeListeners 406: fireStateChanged(); 407: } 408: 409: /** 410: * Get the value of the model's "pressed" property. 411: * 412: * @return The current "pressed" property 413: */ 414: public boolean isPressed() 415: { 416: return (stateMask & PRESSED) == PRESSED; 417: } 418: 419: /** 420: * Set the value of the model's "rollover" property. 421: * 422: * @param r The new "rollover" property 423: */ 424: public void setRollover(boolean r) 425: { 426: // if this call does not represent a CHANGE in state, then return 427: if ((r && isRollover()) || (!r && !isRollover())) 428: return; 429: 430: // cannot set ROLLOVER property unless button is enabled 431: if (!isEnabled()) 432: return; 433: 434: // make the change 435: if (r) 436: stateMask = stateMask | ROLLOVER; 437: else 438: stateMask = stateMask & (~ROLLOVER); 439: 440: // notify interested ChangeListeners 441: fireStateChanged(); 442: } 443: 444: /** 445: * Set the value of the model's "selected" property. 446: * 447: * @param s The new "selected" property 448: */ 449: public void setSelected(boolean s) 450: { 451: // if this call does not represent a CHANGE in state, then return 452: if ((s && isSelected()) || (!s && !isSelected())) 453: return; 454: 455: // make the change 456: if (s) 457: stateMask = stateMask | SELECTED; 458: else 459: stateMask = stateMask & (~SELECTED); 460: 461: // notify interested ChangeListeners 462: fireStateChanged(); 463: 464: // fire ItemStateChanged events 465: if (s) 466: { 467: fireItemStateChanged(new ItemEvent(this, ItemEvent.ITEM_STATE_CHANGED, 468: null, ItemEvent.SELECTED)); 469: if (group != null) 470: group.setSelected(this, true); 471: } 472: else 473: { 474: fireItemStateChanged(new ItemEvent(this, ItemEvent.ITEM_STATE_CHANGED, 475: null, ItemEvent.DESELECTED)); 476: if (group != null) 477: group.setSelected(this, false); 478: } 479: } 480: 481: /** 482: * Get the value of the model's "selected" property. 483: * 484: * @return The current "selected" property 485: */ 486: public boolean isSelected() 487: { 488: return (stateMask & SELECTED) == SELECTED; 489: } 490: 491: /** 492: * Get the value of the model's "rollover" property. 493: * 494: * @return The current "rollover" property 495: */ 496: public boolean isRollover() 497: { 498: return (stateMask & ROLLOVER) == ROLLOVER; 499: } 500: 501: /** 502: * Get the value of the model's "mnemonic" property. 503: * 504: * @return The current "mnemonic" property 505: */ 506: public int getMnemonic() 507: { 508: return mnemonic; 509: } 510: 511: /** 512: * Set the value of the model's "mnemonic" property. 513: * 514: * @param key The new "mnemonic" property 515: */ 516: public void setMnemonic(int key) 517: { 518: if (mnemonic != key) 519: { 520: mnemonic = key; 521: fireStateChanged(); 522: } 523: } 524: 525: /** 526: * Set the value of the model's "actionCommand" property. This property is 527: * used as the "command" property of the {@link ActionEvent} fired from the 528: * model. 529: * 530: * @param s The new "actionCommand" property. 531: */ 532: public void setActionCommand(String s) 533: { 534: if (actionCommand != s) 535: { 536: actionCommand = s; 537: fireStateChanged(); 538: } 539: } 540: 541: /** 542: * Returns the current value of the model's "actionCommand" property. 543: * 544: * @return The current "actionCommand" property 545: */ 546: public String getActionCommand() 547: { 548: return actionCommand; 549: } 550: 551: /** 552: * Set the value of the model's "group" property. The model is said to be a 553: * member of the {@link ButtonGroup} held in its "group" property, and only 554: * one model in a given group can have their "selected" property be 555: * <code>true</code> at a time. 556: * 557: * @param g The new "group" property 558: */ 559: public void setGroup(ButtonGroup g) 560: { 561: if (group != g) 562: { 563: group = g; 564: fireStateChanged(); 565: } 566: } 567: 568: /** 569: * Returns the current value of the model's "group" property. 570: * 571: * @return The value of the "group" property 572: */ 573: public ButtonGroup getGroup() 574: { 575: return group; 576: } 577: }
GNU Classpath (0.18) |