# Java AWT: Popup Menu

## Purpose

Popup menus (also known as "context menus") are now a very common UI element in modern GUIs (Win95, CDE, etc.). The AWT in 1.0 supports only Pulldown menus (menus which are always attached to a menubar or menu-item) and needs an API to allow Java programs to be able to easily create popup menus.

## Popup Menu API

The primary goal for this API is to make the creation and invocation of popups extremely easy in Java programs. Additionally, we want to ensure that popups are not tightly bound to a single component and can be easily reused both within , as well as across, containment hierarchies.

The API consists of a new subclass of Menu:

    	java.awt.PopupMenu

The main addition to this subclass is a method to invoke the popup:

    	public void show(Component origin, int x, int y)

This method will invoke the popup at the x,y coordinate position relative to the component parameter (the intention is that all parameters can easily be extracted from a given mouse-down event object).

### Popup Menu Ownership

Popup menus must have a valid "parent" component in order to be shown. This is to ensure that a popup menu can be instantiated and cached prior to being shown (to prevent any potential slow-down during the show operation, which from the user's perspective should happen simultaneously with the mouse event which triggered it). Popup menus can be attached-to/removed-from any component, using new methods in class java.awt.Component:

    	add(PopupMenu popup)

    	remove(MenuComponent popup)

Note that a popup menu can only be owned by one component at a time.

The "origin" parameter passed into the show() method can be any component contained within the containment hierarchy defined with the popup's parent as the root (it need not be the parent itself). This is particularly useful if you need to define a single popup for an entire window; you would attach the popup menu to the frame, but could invoke it in response to a mouse-down event on any component within that frame.

### Popup Event Trigger

The main issue with popup menus is defining an appropriate event trigger definition, as this varies slightly across the different platforms:

- In Windows, the menu is popped up on the mouse button *2* mouse UP.
- In Motif, the menu is popped up on the mouse button *3* mouse DOWN (and it remains showing if the subsequent mouse UP happens within a small interval; else the menu is pulled down on the mouse DOWN)

The API provides a platform-independent abstraction so a program can detect a popup-menu trigger event without hard-coding platform-specific event-handling logic in the program. This is accomplished by providing the following method on java.awt.event.MouseEvent:

    	public boolean isPopupTrigger()

### Event Model Issues

The AWT's 1.0 event model has a limitation where menu events (the actions invoked when a menu item is selected) are not catchable in the menu itself, but must be caught on the parent frame. To work with the 1.0 event model, the popup menu events must be caught in the action() method of the component which owns it. Clearly this is not a desirable limitation for popup menus, as they are not designed to be tightly bound to a particular component. With the new 1.1 event model API, action listeners can be attached directly to the menu items themselves, alleviating this issue (See the AWT Delegation Event Model document for details).

## Sample Code

Following is a very simple sample program which shows the usage of this API using the 1.1 Delegation Event Model.

        import java.awt.*;
        import java.applet.*;
        import java.awt.event.*;

        public class PopupMenuTest extends Applet implements ActionListener {

    	PopupMenu popup;

    	public void init() {
                MenuItem mi;

    	    popup = new PopupMenu("Edit");

                mi = new MenuItem("Cut");
                mi.addActionListener(this);
    	    popup.add(mi);

                mi = new MenuItem("Copy");
                mi.addActionListener(this);
    	    popup.add(mi);

    	    popup.addSeparator();

                mi = new MenuItem("Paste");
                mi.addActionListener(this);
    	    popup.add(mi);

    	    add(popup); // add popup menu to applet

                enableEvents(AWTEvent.MOUSE_EVENT_MASK);

    	    resize(200, 200);
            }

    	public void processMouseEvent(MouseEvent e) {

    	    if (e.isPopupTrigger()) {
    	        popup.show(e.getComponent(), e.getX(), e.getY());
    	    }
    	    super.processMouseEvent(e);
            }

            public void actionPerformed(ActionEvent e) {
    	    String command = e.getActionCommand();

                if (command.equals("Cut")) {
    	        // perform cut operation
                } else if (command.equals("Copy")) {
                    // perform copy operation
                } else if (command.equals("Paste")) {
                    // perform paste operation
                }
            }
        }

Copyright © 1996, Sun Microsystems, Inc. All rights reserved.