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