content: package com.actelion.research.gui;
  
  import javax.swing.Action;
  import javax.swing.JButton;
  import javax.swing.JMenu;
  import javax.swing.JMenuItem;
  import javax.swing.JPopupMenu;
  import javax.swing.MenuElement;
  import javax.swing.UIManager;
  import javax.swing.plaf.MenuItemUI;
  import javax.swing.plaf.PopupMenuUI;
  import java.awt.Component;
  import java.awt.ComponentOrientation;
  
  
  
  public class JScrollableMenu extends JMenu {
  	// Covers the one in the JMenu because the method that creates it in JMenu is private
  	/** The popup menu portion of the menu.*/
  	private JPopupMenu popupMenu;
  
  
  	/**
  	 * Constructs a new <code>JMenu</code> with no text.
  	 */
  	public JScrollableMenu() {
  		this("");
  	}
  
  	/**
  	 * Constructs a new <code>JMenu</code> with the supplied string as its text.
  	 *
  	 * @param s the text for the menu label
  	 */
  	public JScrollableMenu(String s) {
  		super(s);
  	}
  
  	/**
  	 * Constructs a menu whose properties are taken from the <code>Action</code> supplied.
  	 *
  	 * @param a an <code>Action</code>
  	 */
  	public JScrollableMenu(Action a) {
  		this();
  		setAction(a);
  	}
  
  
  	/**
  	 * Lazily creates the popup menu. This method will create the popup using the <code>JScrollablePopupMenu</code> class.
  	 */
  	protected void ensurePopupMenuCreated() {
  		if(popupMenu == null) {
  			popupMenu = new JScrollablePopupMenu();
  			popupMenu.setInvoker(this);
  			popupListener = createWinListener(popupMenu);
  		}
  	}
  
  	//////////////////////////////
  //// All of these methods are necessary because ensurePopupMenuCreated() is private in JMenu
  //////////////////////////////
  	@Override
  	public void updateUI() {
  		setUI((MenuItemUI) UIManager.getUI(this));
  
  		if(popupMenu != null) {
  			popupMenu.setUI((PopupMenuUI) UIManager.getUI(popupMenu));
  		}
  	}
  
  
  	@Override
  	public boolean isPopupMenuVisible() {
  		ensurePopupMenuCreated();
  		return popupMenu.isVisible();
  	}
  
  
  	@Override
  	public void setMenuLocation(int x, int y) {
  		super.setMenuLocation(x, y);
  		if(popupMenu != null) {
  			popupMenu.setLocation(x, y);
  		}
  	}
  
  	@Override
  	public JMenuItem add(JMenuItem menuItem) {
  		ensurePopupMenuCreated();
  		return popupMenu.add(menuItem);
  	}
  
  	@Override
  	public Component add(Component c) {
  		ensurePopupMenuCreated();
  		popupMenu.add(c);
  		return c;
  	}
  
  	@Override
  	public Component add(Component c, int index) {
  		ensurePopupMenuCreated();
  		popupMenu.add(c, index);
  		return c;
  	}
  
  
  	@Override
  	public void addSeparator() {
  		ensurePopupMenuCreated();
  		popupMenu.addSeparator();
  	}
  
  	@Override
  	public void insert(String s, int pos) {
  		if(pos < 0) {
  			throw new IllegalArgumentException("index less than zero.");
  		}
  
  		ensurePopupMenuCreated();
  		popupMenu.insert(new JMenuItem(s), pos);
  	}
  
  	@Override
  	public JMenuItem insert(JMenuItem mi, int pos) {
  		if(pos < 0) {
  			throw new IllegalArgumentException("index less than zero.");
  		}
  		ensurePopupMenuCreated();
  		popupMenu.insert(mi, pos);
  		return mi;
  	}
  
  	@Override
  	public JMenuItem insert(Action a, int pos) {
  		if(pos < 0) {
  			throw new IllegalArgumentException("index less than zero.");
  		}
  
  		ensurePopupMenuCreated();
  		JMenuItem mi = new JMenuItem(a);
  		mi.setHorizontalTextPosition(JButton.TRAILING);
  		mi.setVerticalTextPosition(JButton.CENTER);
  		popupMenu.insert(mi, pos);
  		return mi;
  	}
  
  	@Override
  	public void insertSeparator(int index) {
  		if(index < 0) {
  			throw new IllegalArgumentException("index less than zero.");
  		}
  
  		ensurePopupMenuCreated();
  		popupMenu.insert(new JPopupMenu.Separator(), index);
  	}
  
  
  	@Override
  	public void remove(JMenuItem item) {
  		if(popupMenu != null){
  			popupMenu.remove(item);
  		}
  	}
  
  	@Override
  	public void remove(int pos) {
  		if(pos < 0) {
  			throw new IllegalArgumentException("index less than zero.");
  		}
  		if(pos > getItemCount()) {
  			throw new IllegalArgumentException("index greater than the number of items.");
  		}
  		if(popupMenu != null){
  			popupMenu.remove(pos);
  		}
  	}
  
  	@Override
  	public void remove(Component c) {
  		if(popupMenu != null){
  			popupMenu.remove(c);
  		}
  	}
  
  	@Override
  	public void removeAll() {
  		popupMenu = null;
  	}
  
  	@Override
  	public int getMenuComponentCount() {
  		return (popupMenu == null) ? 0 : popupMenu.getComponentCount();
  	}
  
  	@Override
  	public Component getMenuComponent(int n) {
  		return (popupMenu == null) ? null : popupMenu.getComponent(n);
  	}
  
  	@Override
  	public Component[] getMenuComponents() {
  		return (popupMenu == null) ? new Component[0] : popupMenu.getComponents();
  	}
  
  	@Override
  	public JPopupMenu getPopupMenu() {
  		ensurePopupMenuCreated();
  		return popupMenu;
  	}
  
  	@Override
  	public MenuElement[] getSubElements() {
  		return popupMenu == null ? new MenuElement[0] : new MenuElement[]{popupMenu};
  	}
  
  
  	@Override
  	public void applyComponentOrientation(ComponentOrientation o) {
  		super.applyComponentOrientation(o);
  
  		if(popupMenu != null) {
  			int ncomponents = getMenuComponentCount();
  			for(int i = 0; i < ncomponents; ++i) {
  				getMenuComponent(i).applyComponentOrientation(o);
  			}
  			popupMenu.setComponentOrientation(o);
  		}
  	}
  
  	@Override
  	public void setComponentOrientation(ComponentOrientation o) {
  		super.setComponentOrientation(o);
  		if(popupMenu != null) {
  			popupMenu.setComponentOrientation(o);
  		}
  	}
  }