Java AWT: Popup Menu


Last Updated: October 8, 1996

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:

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. To accomplish this, a "popup trigger" flag will be added to the appropriate event class (java.awt.Event for the 1.0 event model and java.awt.event.MouseEvent for the new 1.1 event model) and this flag will be set when an event maps to the appropriate popup menu trigger on a given platform. This way a Java program can check for the validity of this flag in the appropriate event handling code to determine whether or not to popup the menu.

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.0 event model). Note that "this" is pass into the show() method rather than "e.target". This is because as mouse events are propagated up a containment hierarchy, the x,y coordinate is always translated to be relative to the component on which handleEvent() is being called.

	import awt.*;
	public class popupMenuTest extends Applet {
	    PopupMenu popup;
	    public void init() {	    
	        popup = new PopupMenu("Edit");
	        popup.add("Cut");
	        popup.add("Copy");
	        popup.addSeparator();
	        popup.add("Paste");
	        add(popup);
	        resize(200, 200);
		}
	    public boolean handleEvent(Event e) {
	        if (e.flags & Event.POPUP_TRIGGER) { 
	            popup.show(this, e.x, e.y);
	            return true;
	        }
	        return super.handleEvent(e);
	    }
	    public boolean action(Event e, Object arg) {
	        if ("Cut".equals(arg)) {
	            // perform cut operation
	            return true;
	        } else if ("Copy".equals(arg)) {
	            // perform copy operation
	            return true;
	        } else if ("Paste".equals(arg)) {
	            // perform paste operation
	            return true;
	        }
	        return false;
	    }
	}
	



Send feedback to:java-awt@java.sun.com
Copyright © 1996, Sun Microsystems, Inc. All rights reserved.