GNU Classpath (0.19) | ||
Frames | No Frames |
1: /* JMenuItem.java -- 2: Copyright (C) 2002, 2004, 2005 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.Component; 42: import java.awt.event.InputEvent; 43: import java.awt.event.KeyEvent; 44: import java.awt.event.MouseEvent; 45: import java.beans.PropertyChangeEvent; 46: import java.beans.PropertyChangeListener; 47: import java.util.EventListener; 48: 49: import javax.accessibility.Accessible; 50: import javax.accessibility.AccessibleContext; 51: import javax.accessibility.AccessibleRole; 52: import javax.swing.event.ChangeEvent; 53: import javax.swing.event.ChangeListener; 54: import javax.swing.event.MenuDragMouseEvent; 55: import javax.swing.event.MenuDragMouseListener; 56: import javax.swing.event.MenuKeyEvent; 57: import javax.swing.event.MenuKeyListener; 58: import javax.swing.plaf.MenuItemUI; 59: 60: /** 61: * JMenuItem represents element in the menu. It inherits most of 62: * its functionality from AbstractButton, however its behavior somewhat 63: * varies from it. JMenuItem fire different kinds of events. 64: * PropertyChangeEvents are fired when menuItems properties are modified; 65: * ChangeEvents are fired when menuItem's state changes and actionEvents are 66: * fired when menu item is selected. In addition to this events menuItem also 67: * fire MenuDragMouseEvent and MenuKeyEvents when mouse is dragged over 68: * the menu item or associated key with menu item is invoked respectively. 69: */ 70: public class JMenuItem extends AbstractButton implements Accessible, 71: MenuElement 72: { 73: private static final long serialVersionUID = -1681004643499461044L; 74: 75: /** Combination of keyboard keys that can be used to activate this menu item */ 76: private KeyStroke accelerator; 77: 78: /** 79: * Creates a new JMenuItem object. 80: */ 81: public JMenuItem() 82: { 83: super(); 84: init(null, null); 85: } 86: 87: /** 88: * Creates a new JMenuItem with the given icon. 89: * 90: * @param icon Icon that will be displayed on the menu item 91: */ 92: public JMenuItem(Icon icon) 93: { 94: // FIXME: The requestedFocusEnabled property should 95: // be set to false, when only icon is set for menu item. 96: super(); 97: init(null, icon); 98: } 99: 100: /** 101: * Creates a new JMenuItem with the given label. 102: * 103: * @param text label for the menu item 104: */ 105: public JMenuItem(String text) 106: { 107: this(text, null); 108: } 109: 110: /** 111: * Creates a new JMenuItem associated with the specified action. 112: * 113: * @param action action for this menu item 114: */ 115: public JMenuItem(Action action) 116: { 117: super(); 118: super.setAction(action); 119: init(null, null); 120: } 121: 122: /** 123: * Creates a new JMenuItem with specified text and icon. 124: * Text is displayed to the left of icon by default. 125: * 126: * @param text label for this menu item 127: * @param icon icon that will be displayed on this menu item 128: */ 129: public JMenuItem(String text, Icon icon) 130: { 131: super(); 132: init(text, icon); 133: } 134: 135: /** 136: * Creates a new JMenuItem object. 137: * 138: * @param text label for this menu item 139: * @param mnemonic - Single key that can be used with a 140: * look-and-feel meta key to activate this menu item. However 141: * menu item should be visible on the screen when mnemonic is used. 142: */ 143: public JMenuItem(String text, int mnemonic) 144: { 145: this(text, null); 146: setMnemonic(mnemonic); 147: } 148: 149: /** 150: * Initializes this menu item 151: * 152: * @param text label for this menu item 153: * @param icon icon to be displayed for this menu item 154: */ 155: protected void init(String text, Icon icon) 156: { 157: super.init(text, icon); 158: setModel(new DefaultButtonModel()); 159: 160: // Initializes properties for this menu item, that are different 161: // from Abstract button properties. 162: /* NOTE: According to java specifications paint_border should be set to false, 163: since menu item should not have a border. However running few java programs 164: it seems that menu items and menues can have a border. Commenting 165: out statement below for now. */ 166: //borderPainted = false; 167: focusPainted = false; 168: horizontalAlignment = JButton.LEFT; 169: horizontalTextPosition = JButton.TRAILING; 170: } 171: 172: /** 173: * Set the "UI" property of the menu item, which is a look and feel class 174: * responsible for handling menuItem's input events and painting it. 175: * 176: * @param ui The new "UI" property 177: */ 178: public void setUI(MenuItemUI ui) 179: { 180: super.setUI(ui); 181: } 182: 183: /** 184: * This method sets this menuItem's UI to the UIManager's default for the 185: * current look and feel. 186: */ 187: public void updateUI() 188: { 189: MenuItemUI mi = ((MenuItemUI) UIManager.getUI(this)); 190: setUI(mi); 191: invalidate(); 192: } 193: 194: /** 195: * This method returns a name to identify which look and feel class will be 196: * the UI delegate for the menuItem. 197: * 198: * @return The Look and Feel classID. "MenuItemUI" 199: */ 200: public String getUIClassID() 201: { 202: return "MenuItemUI"; 203: } 204: 205: /** 206: * Returns true if button's model is armed and false otherwise. The 207: * button model is armed if menu item has focus or it is selected. 208: * 209: * @return $boolean$ true if button's model is armed and false otherwise 210: */ 211: public boolean isArmed() 212: { 213: return getModel().isArmed(); 214: } 215: 216: /** 217: * Sets menuItem's "ARMED" property 218: * 219: * @param armed DOCUMENT ME! 220: */ 221: public void setArmed(boolean armed) 222: { 223: getModel().setArmed(armed); 224: } 225: 226: /** 227: * Enable or disable menu item. When menu item is disabled, 228: * its text and icon are grayed out if they exist. 229: * 230: * @param enabled if true enable menu item, and disable otherwise. 231: */ 232: public void setEnabled(boolean enabled) 233: { 234: super.setEnabled(enabled); 235: } 236: 237: /** 238: * Return accelerator for this menu item. 239: * 240: * @return $KeyStroke$ accelerator for this menu item. 241: */ 242: public KeyStroke getAccelerator() 243: { 244: return accelerator; 245: } 246: 247: /** 248: * Sets the key combination which invokes the menu item's action 249: * listeners without navigating the menu hierarchy. Note that when the 250: * keyboard accelerator is typed, it will work whether or not the 251: * menu is currently displayed. 252: * 253: * @param keystroke accelerator for this menu item. 254: */ 255: public void setAccelerator(KeyStroke keystroke) 256: { 257: this.accelerator = keystroke; 258: } 259: 260: /** 261: * Configures menu items' properties from properties of the specified action. 262: * This method overrides configurePropertiesFromAction from AbstractButton 263: * to also set accelerator property. 264: * 265: * @param action action to configure properties from 266: */ 267: protected void configurePropertiesFromAction(Action action) 268: { 269: super.configurePropertiesFromAction(action); 270: 271: if (! (this instanceof JMenu) && action != null) 272: { 273: setAccelerator((KeyStroke) (action.getValue(Action.ACCELERATOR_KEY))); 274: super.registerKeyboardAction(action, accelerator, 275: JComponent.WHEN_IN_FOCUSED_WINDOW); 276: } 277: } 278: 279: /** 280: * Creates PropertyChangeListener to listen for the changes in action 281: * properties. 282: * 283: * @param action action to listen to for property changes 284: * 285: * @return $PropertyChangeListener$ Listener that listens to changes in 286: * action properties. 287: */ 288: protected PropertyChangeListener createActionPropertyChangeListener(Action action) 289: { 290: return new PropertyChangeListener() 291: { 292: public void propertyChange(PropertyChangeEvent e) 293: { 294: Action act = (Action) (e.getSource()); 295: configurePropertiesFromAction(act); 296: } 297: }; 298: } 299: 300: /** 301: * Process mouse events forwarded from MenuSelectionManager. 302: * 303: * @param event event forwarded from MenuSelectionManager 304: * @param path path to the menu element from which event was generated 305: * @param manager MenuSelectionManager for the current menu hierarchy 306: */ 307: public void processMouseEvent(MouseEvent event, MenuElement[] path, 308: MenuSelectionManager manager) 309: { 310: // Fire MenuDragMouseEvents if mouse is being dragged. 311: boolean dragged 312: = (event.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK) != 0; 313: if (dragged) 314: processMenuDragMouseEvent(createMenuDragMouseEvent(event, path, manager)); 315: 316: switch (event.getID()) 317: { 318: case MouseEvent.MOUSE_CLICKED: 319: break; 320: case MouseEvent.MOUSE_ENTERED: 321: if (isRolloverEnabled()) 322: model.setRollover(true); 323: break; 324: case MouseEvent.MOUSE_EXITED: 325: if (isRolloverEnabled()) 326: model.setRollover(false); 327: 328: // for JMenu last element on the path is its popupMenu. 329: // JMenu shouldn't me disarmed. 330: if (! (path[path.length - 1] instanceof JPopupMenu) && ! dragged) 331: setArmed(false); 332: break; 333: case MouseEvent.MOUSE_PRESSED: 334: if ((event.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK) != 0) 335: { 336: model.setArmed(true); 337: model.setPressed(true); 338: } 339: break; 340: case MouseEvent.MOUSE_RELEASED: 341: break; 342: case MouseEvent.MOUSE_MOVED: 343: break; 344: case MouseEvent.MOUSE_DRAGGED: 345: break; 346: } 347: } 348: 349: /** 350: * Creates MenuDragMouseEvent. 351: * 352: * @param event MouseEvent that occured while mouse was pressed. 353: * @param path Path the the menu element where the dragging event was 354: * originated 355: * @param manager MenuSelectionManager for the current menu hierarchy. 356: * 357: * @return new MenuDragMouseEvent 358: */ 359: private MenuDragMouseEvent createMenuDragMouseEvent(MouseEvent event, 360: MenuElement[] path, 361: MenuSelectionManager manager) 362: { 363: return new MenuDragMouseEvent((Component) event.getSource(), 364: event.getID(), event.getWhen(), 365: event.getModifiers(), event.getX(), 366: event.getY(), event.getClickCount(), 367: event.isPopupTrigger(), path, manager); 368: } 369: 370: /** 371: * Process key events forwarded from MenuSelectionManager. 372: * 373: * @param event event forwarded from MenuSelectionManager 374: * @param path path to the menu element from which event was generated 375: * @param manager MenuSelectionManager for the current menu hierarchy 376: */ 377: public void processKeyEvent(KeyEvent event, MenuElement[] path, 378: MenuSelectionManager manager) 379: { 380: // Need to implement. 381: } 382: 383: /** 384: * This method fires MenuDragMouseEvents to registered listeners. 385: * Different types of MenuDragMouseEvents are fired depending 386: * on the observed mouse event. 387: * 388: * @param event Mouse 389: */ 390: public void processMenuDragMouseEvent(MenuDragMouseEvent event) 391: { 392: switch (event.getID()) 393: { 394: case MouseEvent.MOUSE_ENTERED: 395: fireMenuDragMouseEntered(event); 396: break; 397: case MouseEvent.MOUSE_EXITED: 398: fireMenuDragMouseExited(event); 399: break; 400: case MouseEvent.MOUSE_DRAGGED: 401: fireMenuDragMouseDragged(event); 402: break; 403: case MouseEvent.MOUSE_RELEASED: 404: fireMenuDragMouseReleased(event); 405: break; 406: } 407: } 408: 409: /** 410: * This method fires MenuKeyEvent to registered listeners. 411: * Different types of MenuKeyEvents are fired depending 412: * on the observed key event. 413: * 414: * @param event DOCUMENT ME! 415: */ 416: public void processMenuKeyEvent(MenuKeyEvent event) 417: { 418: // Need to implement. 419: } 420: 421: /** 422: * Fires MenuDragMouseEvent to all of the menuItem's MouseInputListeners. 423: * 424: * @param event The event signifying that mouse entered menuItem while it was dragged 425: */ 426: protected void fireMenuDragMouseEntered(MenuDragMouseEvent event) 427: { 428: EventListener[] ll = listenerList.getListeners(MenuDragMouseListener.class); 429: 430: for (int i = 0; i < ll.length; i++) 431: ((MenuDragMouseListener) ll[i]).menuDragMouseEntered(event); 432: } 433: 434: /** 435: * Fires MenuDragMouseEvent to all of the menuItem's MouseInputListeners. 436: * 437: * @param event The event signifying that mouse has exited menu item, while it was dragged 438: */ 439: protected void fireMenuDragMouseExited(MenuDragMouseEvent event) 440: { 441: EventListener[] ll = listenerList.getListeners(MenuDragMouseListener.class); 442: 443: for (int i = 0; i < ll.length; i++) 444: ((MenuDragMouseListener) ll[i]).menuDragMouseExited(event); 445: } 446: 447: /** 448: * Fires MenuDragMouseEvent to all of the menuItem's MouseInputListeners. 449: * 450: * @param event The event signifying that mouse is being dragged over the menuItem 451: */ 452: protected void fireMenuDragMouseDragged(MenuDragMouseEvent event) 453: { 454: EventListener[] ll = listenerList.getListeners(MenuDragMouseListener.class); 455: 456: for (int i = 0; i < ll.length; i++) 457: ((MenuDragMouseListener) ll[i]).menuDragMouseDragged(event); 458: } 459: 460: /** 461: * This method fires a MenuDragMouseEvent to all the MenuItem's MouseInputListeners. 462: * 463: * @param event The event signifying that mouse was released while it was dragged over the menuItem 464: */ 465: protected void fireMenuDragMouseReleased(MenuDragMouseEvent event) 466: { 467: EventListener[] ll = listenerList.getListeners(MenuDragMouseListener.class); 468: 469: for (int i = 0; i < ll.length; i++) 470: ((MenuDragMouseListener) ll[i]).menuDragMouseReleased(event); 471: } 472: 473: /** 474: * This method fires a MenuKeyEvent to all the MenuItem's MenuKeyListeners. 475: * 476: * @param event The event signifying that key associated with this menu was pressed 477: */ 478: protected void fireMenuKeyPressed(MenuKeyEvent event) 479: { 480: EventListener[] ll = listenerList.getListeners(MenuKeyListener.class); 481: 482: for (int i = 0; i < ll.length; i++) 483: ((MenuKeyListener) ll[i]).menuKeyPressed(event); 484: } 485: 486: /** 487: * This method fires a MenuKeyEvent to all the MenuItem's MenuKeyListeners. 488: * 489: * @param event The event signifying that key associated with this menu was released 490: */ 491: protected void fireMenuKeyReleased(MenuKeyEvent event) 492: { 493: EventListener[] ll = listenerList.getListeners(MenuKeyListener.class); 494: 495: for (int i = 0; i < ll.length; i++) 496: ((MenuKeyListener) ll[i]).menuKeyTyped(event); 497: } 498: 499: /** 500: * This method fires a MenuKeyEvent to all the MenuItem's MenuKeyListeners. 501: * 502: * @param event The event signifying that key associated with this menu was typed. 503: * The key is typed when it was pressed and then released 504: */ 505: protected void fireMenuKeyTyped(MenuKeyEvent event) 506: { 507: EventListener[] ll = listenerList.getListeners(MenuKeyListener.class); 508: 509: for (int i = 0; i < ll.length; i++) 510: ((MenuKeyListener) ll[i]).menuKeyTyped(event); 511: } 512: 513: /** 514: * Method of the MenuElement interface. 515: * This method is invoked by MenuSelectionManager when selection of 516: * this menu item has changed. If this menu item was selected then 517: * arm it's model, and disarm the model otherwise. The menu item 518: * is considered to be selected, and thus highlighted when its model 519: * is armed. 520: * 521: * @param changed indicates selection status of this menu item. If changed is 522: * true then menu item is selected and deselected otherwise. 523: */ 524: public void menuSelectionChanged(boolean changed) 525: { 526: Component parent = this.getParent(); 527: if (changed) 528: { 529: model.setArmed(true); 530: 531: if (parent != null && parent instanceof JPopupMenu) 532: ((JPopupMenu) parent).setSelected(this); 533: } 534: else 535: { 536: model.setArmed(false); 537: 538: if (parent != null && parent instanceof JPopupMenu) 539: ((JPopupMenu) parent).getSelectionModel().clearSelection(); 540: } 541: } 542: 543: /** 544: * Method of the MenuElement interface. 545: * 546: * @return $MenuElement[]$ Returns array of sub-components for this menu 547: * item. By default menuItem doesn't have any subcomponents and so 548: * empty array is returned instead. 549: */ 550: public MenuElement[] getSubElements() 551: { 552: return new MenuElement[0]; 553: } 554: 555: /** 556: * Returns reference to the component that will paint this menu item. 557: * 558: * @return $Component$ Component that will paint this menu item. 559: * Simply returns reference to this menu item. 560: */ 561: public Component getComponent() 562: { 563: return this; 564: } 565: 566: /** 567: * Adds a MenuDragMouseListener to this menu item. When mouse 568: * is dragged over the menu item the MenuDragMouseEvents will be 569: * fired, and these listeners will be called. 570: * 571: * @param listener The new listener to add 572: */ 573: public void addMenuDragMouseListener(MenuDragMouseListener listener) 574: { 575: listenerList.add(MenuDragMouseListener.class, listener); 576: } 577: 578: /** 579: * Removes a MenuDragMouseListener from the menuItem's listener list. 580: * 581: * @param listener The listener to remove 582: */ 583: public void removeMenuDragMouseListener(MenuDragMouseListener listener) 584: { 585: listenerList.remove(MenuDragMouseListener.class, listener); 586: } 587: 588: /** 589: * Returns all added MenuDragMouseListener objects. 590: * 591: * @return an array of listeners 592: * 593: * @since 1.4 594: */ 595: public MenuDragMouseListener[] getMenuDragMouseListeners() 596: { 597: return (MenuDragMouseListener[]) listenerList.getListeners(MenuDragMouseListener.class); 598: } 599: 600: /** 601: * Adds an MenuKeyListener to this menu item. This listener will be 602: * invoked when MenuKeyEvents will be fired by this menu item. 603: * 604: * @param listener The new listener to add 605: */ 606: public void addMenuKeyListener(MenuKeyListener listener) 607: { 608: listenerList.add(MenuKeyListener.class, listener); 609: } 610: 611: /** 612: * Removes an MenuKeyListener from the menuItem's listener list. 613: * 614: * @param listener The listener to remove 615: */ 616: public void removeMenuKeyListener(MenuKeyListener listener) 617: { 618: listenerList.remove(MenuKeyListener.class, listener); 619: } 620: 621: /** 622: * Returns all added MenuKeyListener objects. 623: * 624: * @return an array of listeners 625: * 626: * @since 1.4 627: */ 628: public MenuKeyListener[] getMenuKeyListeners() 629: { 630: return (MenuKeyListener[]) listenerList.getListeners(MenuKeyListener.class); 631: } 632: 633: /** 634: * A string that describes this JMenuItem. Normally only used 635: * for debugging. 636: * 637: * @return A string describing this JMenuItem 638: */ 639: protected String paramString() 640: { 641: return super.paramString(); 642: } 643: 644: public AccessibleContext getAccessibleContext() 645: { 646: if (accessibleContext == null) 647: accessibleContext = new AccessibleJMenuItem(); 648: 649: return accessibleContext; 650: } 651: 652: protected class AccessibleJMenuItem extends AccessibleAbstractButton 653: implements ChangeListener 654: { 655: private static final long serialVersionUID = 6748924232082076534L; 656: 657: /** 658: * Creates a new AccessibleJMenuItem object. 659: */ 660: AccessibleJMenuItem() 661: { 662: //super(component); 663: } 664: 665: public void stateChanged(ChangeEvent event) 666: { 667: // TODO: What should be done here, if anything? 668: } 669: 670: public AccessibleRole getAccessibleRole() 671: { 672: return AccessibleRole.MENU_ITEM; 673: } 674: } 675: }
GNU Classpath (0.19) |