home *** CD-ROM | disk | FTP | other *** search
/ Java 1.2 How-To / JavaHowTo.iso / 3rdParty / jbuilder / unsupported / JDK1.2beta3 / SOURCE / SRC.ZIP / java / awt / MenuItem.java < prev    next >
Encoding:
Java Source  |  1998-03-20  |  14.8 KB  |  488 lines

  1. /*
  2.  * @(#)MenuItem.java    1.47 98/03/18
  3.  *
  4.  * Copyright 1995-1997 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14. package java.awt;
  15.  
  16. import java.awt.peer.MenuItemPeer;
  17. import java.awt.event.*;
  18. import java.io.ObjectOutputStream;
  19. import java.io.ObjectInputStream;
  20. import java.io.IOException;
  21.  
  22.  
  23. /**
  24.  * All items in a menu must belong to the class 
  25.  * <code>MenuItem</code, or one of its subclasses.
  26.  * <p>
  27.  * The default <code>MenuItem</code> object embodies
  28.  * a simple labeled menu item. 
  29.  * <p>
  30.  * This picture of a menu bar shows five menu items:
  31.  * <IMG SRC="images-awt/MenuBar-1.gif" 
  32.  * ALIGN=CENTER HSPACE=10 VSPACE=7> 
  33.  * <br CLEAR=LEFT>
  34.  * The first two items are simple menu items, labeled 
  35.  * <code>"Basic"</code> and <code>"Simple"</code>. 
  36.  * Following these two items is a separator, which is itself
  37.  * a menu item, created with the label <code>"-"</code>. 
  38.  * Next is an instance of <code>CheckboxMenuItem</code> 
  39.  * labeled <code>"Check"</code>. The final menu item is a 
  40.  * submenu labeled <code>"More Examples"</code>, 
  41.  * and this submenu is an instance of <code>Menu</code>. 
  42.  * <p>
  43.  * When a menu item is selected, AWT sends an action event to 
  44.  * the menu item. Since the event is an
  45.  * instance of <code>ActionEvent</code>, the <code>processEvent</code> 
  46.  * method examines the event and passes it along to 
  47.  * <code>processActionEvent</code>. The latter method redirects the
  48.  * event to any <code>ActionListener</code> objects that have
  49.  * registered an interest in action events generated by this
  50.  * menu item. 
  51.  * <P> 
  52.  * Note that the subclass <code>Menu</code> overrides this behavior and 
  53.  * does not send any event to the frame until one of its subitems is 
  54.  * selected. 
  55.  *
  56.  * @version 1.47, 03/18/98
  57.  * @author Sami Shaio
  58.  */
  59. public class MenuItem extends MenuComponent {
  60.  
  61.     static {
  62.         initIDs();
  63.     }
  64.  
  65.     boolean enabled = true;
  66.     String label;
  67.     String actionCommand;
  68.  
  69.     // The eventMask is ONLY set by subclasses via enableEvents.
  70.     // The mask should NOT be set when listeners are registered
  71.     // so that we can distinguish the difference between when
  72.     // listeners request events and subclasses request them.
  73.     long eventMask;
  74.  
  75.     transient ActionListener actionListener;
  76.  
  77.     private MenuShortcut shortcut = null;
  78.  
  79.     private static final String base = "menuitem";
  80.     private static int nameCounter = 0;
  81.  
  82.     /*
  83.      * JDK 1.1 serialVersionUID 
  84.      */
  85.     private static final long serialVersionUID = -21757335363267194L;
  86.  
  87.     /** 
  88.      * Constructs a new MenuItem with an empty label and no keyboard
  89.      * shortcut.
  90.      * @since    JDK1.1
  91.      */
  92.     public MenuItem() {
  93.     this("", null);
  94.     }
  95.  
  96.     /** 
  97.      * Constructs a new MenuItem with the specified label 
  98.      * and no keyboard shortcut. Note that use of "-" in
  99.      * a label is reserved to indicate a separator between 
  100.      * menu items. By default, all menu items except for 
  101.      * separators are enabled. 
  102.      * @param       label the label for this menu item. 
  103.      * @since       JDK1.0
  104.      */
  105.     public MenuItem(String label) {
  106.     this(label, null);
  107.     }
  108.  
  109.     /**
  110.      * Create a menu item with an associated keyboard shortcut. 
  111.      * Note that use of "-" in a label is reserved to indicate 
  112.      * a separator between menu items. By default, all menu 
  113.      * items except for separators are enabled. 
  114.      * @param       label the label for this menu item. 
  115.      * @param       s the instance of <code>MenuShortcut</code> 
  116.      *                       associated with this menu item. 
  117.      * @since       JDK1.1
  118.      */
  119.     public MenuItem(String label, MenuShortcut s) {
  120.         this.name = base + nameCounter++;
  121.     this.label = label;
  122.         this.shortcut = s;
  123.     }
  124.  
  125.     /**
  126.      * Creates the menu item's peer.  The peer allows us to modify the 
  127.      * appearance of the menu item without changing its functionality.
  128.      */
  129.     public void addNotify() {
  130.     if (peer == null) {
  131.         peer = Toolkit.getDefaultToolkit().createMenuItem(this);
  132.     }
  133.     }
  134.  
  135.     /**
  136.      * Gets the label for this menu item.
  137.      * @return  the label of this menu item, or <code>null</code> 
  138.                        if this menu item has no label.
  139.      * @see     java.awt.MenuItem#setLabel
  140.      * @since   JDK1.0
  141.      */
  142.     public String getLabel() {
  143.     return label;
  144.     }
  145.  
  146.     /**
  147.      * Sets the label for this menu item to the specified label.
  148.      * @param     label   the new label, or <code>null</code> for no label.
  149.      * @see       java.awt.MenuItem#getLabel
  150.      * @since     JDK1.0
  151.      */
  152.     public synchronized void setLabel(String label) {
  153.     this.label = label;
  154.     MenuItemPeer peer = (MenuItemPeer)this.peer;
  155.     if (peer != null) {
  156.         peer.setLabel(label);
  157.     }
  158.     }
  159.  
  160.     /**
  161.      * Checks whether this menu item is enabled.
  162.      * @see        java.awt.MenuItem#setEnabled
  163.      * @since      JDK1.0
  164.      */
  165.     public boolean isEnabled() {
  166.     return enabled;
  167.     }
  168.  
  169.     /**
  170.      * Sets whether or not this menu item can be chosen.
  171.      * @param      b  if <code>true</code>, enables this menu item; 
  172.      *                       if <code>false</code>, disables it.
  173.      * @see        java.awt.MenuItem#isEnabled
  174.      * @since      JDK1.1
  175.      */
  176.     public synchronized void setEnabled(boolean b) {
  177.         enable(b);
  178.     }
  179.  
  180.     /**
  181.      * @deprecated As of JDK version 1.1,
  182.      * replaced by <code>setEnabled(boolean)</code>.
  183.      */
  184.     public synchronized void enable() {
  185.     enabled = true;
  186.     MenuItemPeer peer = (MenuItemPeer)this.peer;
  187.     if (peer != null) {
  188.         peer.enable();
  189.     }
  190.     }
  191.  
  192.     /**
  193.      * @deprecated As of JDK version 1.1,
  194.      * replaced by <code>setEnabled(boolean)</code>.
  195.      */
  196.     public void enable(boolean b) {
  197.         if (b) {
  198.         enable();
  199.     } else {
  200.         disable();
  201.     }
  202.     }
  203.  
  204.     /**
  205.      * @deprecated As of JDK version 1.1,
  206.      * replaced by <code>setEnabled(boolean)</code>.
  207.      */
  208.     public synchronized void disable() {
  209.     enabled = false;
  210.     MenuItemPeer peer = (MenuItemPeer)this.peer;
  211.     if (peer != null) {
  212.         peer.disable();
  213.     }
  214.     }
  215.  
  216.     /**
  217.      * Get the <code>MenuShortcut</code> object associated with this
  218.      * menu item, 
  219.      * @return      the menu shortcut associated with this menu item,
  220.      *                   or <code>null</code> if none has been specified.
  221.      * @see         java.awt.MenuItem#setShortcut
  222.      * @since       JDK1.1
  223.      */
  224.     public MenuShortcut getShortcut() {
  225.         return shortcut;
  226.     }
  227.  
  228.     /** 
  229.      * Set the <code>MenuShortcut</code> object associated with this
  230.      * menu item. If a menu shortcut is already associated with 
  231.      * this menu item, it is replaced.
  232.      * @param       s  the menu shortcut to associate 
  233.      *                           with this menu item.
  234.      * @see         java.awt.MenuItem#getShortcut
  235.      * @since       JDK1.1
  236.      */
  237.     public void setShortcut(MenuShortcut s) {
  238.         shortcut = s;
  239.     MenuItemPeer peer = (MenuItemPeer)this.peer;
  240.     if (peer != null) {
  241.         peer.setLabel(label);
  242.     }
  243.     }
  244.  
  245.     /**
  246.      * Delete any <code>MenuShortcut</code> object associated 
  247.      * with this menu item.
  248.      * @since      JDK1.1
  249.      */
  250.     public void deleteShortcut() {
  251.         shortcut = null;
  252.     MenuItemPeer peer = (MenuItemPeer)this.peer;
  253.     if (peer != null) {
  254.         peer.setLabel(label);
  255.     }
  256.     }
  257.  
  258.     /*
  259.      * Delete a matching MenuShortcut associated with this MenuItem.
  260.      * Used when iterating Menus.
  261.      */
  262.     void deleteShortcut(MenuShortcut s) {
  263.         if (s.equals(shortcut)) {
  264.             shortcut = null;
  265.             MenuItemPeer peer = (MenuItemPeer)this.peer;
  266.             if (peer != null) {
  267.                 peer.setLabel(label);
  268.             }
  269.         }
  270.     }
  271.  
  272.     /*
  273.      * Post an ActionEvent to the target (on 
  274.      * keydown).  Returns true if there is an associated 
  275.      * shortcut.
  276.      */
  277.     boolean handleShortcut(KeyEvent e) {
  278.         MenuShortcut s = new MenuShortcut(e.getKeyCode(), 
  279.                              (e.getModifiers() & InputEvent.SHIFT_MASK) > 0);
  280.         if (s.equals(shortcut) && enabled) {
  281.             // MenuShortcut match -- issue an event on keydown.
  282.             if (e.getID() == KeyEvent.KEY_PRESSED) {
  283.                 Toolkit.getEventQueue().postEvent(
  284.                           new ActionEvent(this, ActionEvent.ACTION_PERFORMED, 
  285.                                           actionCommand));
  286.             } else {
  287.                 // silently eat key release.
  288.             }
  289.             return true;
  290.     }
  291.         return false;
  292.     }
  293.  
  294.     MenuItem getShortcutMenuItem(MenuShortcut s) {
  295.         return (s.equals(shortcut)) ? this : null;
  296.     }
  297.  
  298.     /**
  299.      * Enables event delivery to this menu item for events 
  300.      * to be defined by the specified event mask parameter
  301.      * <p>
  302.      * Since event types are automatically enabled when a listener for 
  303.      * that type is added to the menu item, this method only needs 
  304.      * to be invoked by subclasses of <code>MenuItem</code> which desire to 
  305.      * have the specified event types delivered to <code>processEvent</code> 
  306.      * regardless of whether a listener is registered. 
  307.      * @param       eventsToEnable the event mask defining the event types.
  308.      * @see         java.awt.MenuItem#processEvent
  309.      * @see         java.awt.MenuItem#disableEvents
  310.      * @see         java.awt.Component#enableEvents
  311.      * @since       JDK1.1
  312.      */
  313.     protected final void enableEvents(long eventsToEnable) {
  314.         eventMask |= eventsToEnable;
  315.     }
  316.  
  317.     /**
  318.      * Disables event delivery to this menu item for events 
  319.      * defined by the specified event mask parameter.
  320.      * @param       eventsToDisable the event mask defining the event types.
  321.      * @see         java.awt.MenuItem#processEvent
  322.      * @see         java.awt.MenuItem#enableEvents
  323.      * @see         java.awt.Component#disableEvents
  324.      * @since       JDK1.1
  325.      */
  326.     protected final void disableEvents(long eventsToDisable) {
  327.         eventMask &= ~eventsToDisable;  
  328.     }  
  329.  
  330.     /**
  331.      * Sets the command name of the action event that is fired 
  332.      * by this menu item.
  333.      * <p>
  334.      * By default, the action command is set to the label of 
  335.      * the menu item.
  336.      * @param       command   the action command to be set 
  337.      *                                for this menu item.
  338.      * @see         java.awt.MenuItem#getActionCommand
  339.      * @since       JDK1.1
  340.      */
  341.     public void setActionCommand(String command) {
  342.         actionCommand = command;
  343.     }
  344.  
  345.     /**
  346.      * Gets the command name of the action event that is fired 
  347.      * by this menu item.
  348.      * @see         java.awt.MenuItem#setActionCommand
  349.      * @since       JDK1.1
  350.      */
  351.     public String getActionCommand() {
  352.         return (actionCommand == null? label : actionCommand);
  353.     }
  354.  
  355.     /**
  356.      * Adds the specified action listener to receive action events
  357.      * from this menu item.
  358.      * @param      l the action listener.
  359.      * @see        java.awt.event.ActionEvent
  360.      * @see        java.awt.event.ActionListener
  361.      * @see        java.awt.MenuItem#removeActionListener
  362.      * @since      JDK1.1
  363.      */ 
  364.     public synchronized void addActionListener(ActionListener l) {
  365.     actionListener = AWTEventMulticaster.add(actionListener, l);
  366.         newEventsOnly = true;    
  367.     }
  368.  
  369.     /**
  370.      * Removes the specified action listener so it no longer receives
  371.      * action events from this menu item.
  372.      * @param      l the action listener.
  373.      * @see        java.awt.event.ActionEvent
  374.      * @see        java.awt.event.ActionListener
  375.      * @see        java.awt.MenuItem#addActionListener
  376.      * @since      JDK1.1
  377.      */ 
  378.     public synchronized void removeActionListener(ActionListener l) {
  379.     actionListener = AWTEventMulticaster.remove(actionListener, l);
  380.     }
  381.  
  382.     /**
  383.      * Processes events on this menu item. If the event is an 
  384.      * instance of <code>ActionEvent</code>, it invokes 
  385.      * <code>processActionEvent</code>, another method 
  386.      * defined by <code>MenuItem</code>.
  387.      * <p>
  388.      * Currently, menu items only support action events.
  389.      * @param       e the event.
  390.      * @see         java.awt.MenuItem#processActionEvent
  391.      * @since       JDK1.1
  392.      */
  393.     protected void processEvent(AWTEvent e) {
  394.         if (e instanceof ActionEvent) {
  395.             processActionEvent((ActionEvent)e);     
  396.         }
  397.     }
  398.  
  399.     // REMIND: remove when filtering is done at lower level
  400.     boolean eventEnabled(AWTEvent e) {
  401.         if (e.id == ActionEvent.ACTION_PERFORMED) {
  402.             if ((eventMask & AWTEvent.ACTION_EVENT_MASK) != 0 ||
  403.                 actionListener != null) {
  404.                 return true;
  405.             } 
  406.             return false;
  407.         }
  408.         return super.eventEnabled(e);
  409.     }        
  410.  
  411.     /** 
  412.      * Processes action events occurring on this menu item, 
  413.      * by dispatching them to any registered 
  414.      * <code>ActionListener</code> objects.
  415.      * This method is not called unless action events are 
  416.      * enabled for this component. Action events are enabled 
  417.      * when one of the following occurs:
  418.      * <p><ul>
  419.      * <li>An <code>ActionListener</code> object is registered 
  420.      * via <code>addActionListener</code>.
  421.      * <li>Action events are enabled via <code>enableEvents</code>.
  422.      * </ul>
  423.      * @param       e the action event.
  424.      * @see         java.awt.event.ActionEvent
  425.      * @see         java.awt.event.ActionListener
  426.      * @see         java.awt.MenuItem#enableEvents
  427.      * @since       JDK1.1
  428.      */  
  429.     protected void processActionEvent(ActionEvent e) {
  430.         if (actionListener != null) {
  431.             actionListener.actionPerformed(e);
  432.         }
  433.     }
  434.  
  435.     /**
  436.      * Returns the parameter string representing the state of this menu 
  437.      * item. This string is useful for debugging. 
  438.      * @return  the parameter string of this menu item.
  439.      * @since   JDK1.0
  440.      */
  441.     public String paramString() {
  442.         String str = ",label=" + label;
  443.         if (shortcut != null) {
  444.             str += ",shortcut=" + shortcut;
  445.         }
  446.         return super.paramString() + str;
  447.     }
  448.  
  449.  
  450.     /* Serialization support. 
  451.      */
  452.  
  453.     private int menuItemSerializedDataVersion = 1;
  454.  
  455.  
  456.     private void writeObject(ObjectOutputStream s)
  457.       throws IOException 
  458.     {
  459.       s.defaultWriteObject();
  460.  
  461.       AWTEventMulticaster.save(s, actionListenerK, actionListener);
  462.       s.writeObject(null);
  463.     }
  464.  
  465.  
  466.     private void readObject(ObjectInputStream s)
  467.       throws ClassNotFoundException, IOException 
  468.     {
  469.       s.defaultReadObject();
  470.  
  471.       Object keyOrNull;
  472.       while(null != (keyOrNull = s.readObject())) {
  473.     String key = ((String)keyOrNull).intern();
  474.  
  475.     if (actionListenerK == key) 
  476.       addActionListener((ActionListener)(s.readObject()));
  477.  
  478.     else // skip value for unrecognized key
  479.       s.readObject();
  480.       }
  481.     }
  482.  
  483.     /**
  484.      * Initialize JNI field and method IDs
  485.      */
  486.     private static native void initIDs();
  487. }
  488.