blob: 5465cf959db1af20e88b69baad419fb385e3c8a9 [file] [log] [blame]
/*******************************************************************************
* <copyright>
*
* Copyright (c) 2005, 2010 SAP AG.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* SAP AG - initial API, implementation and documentation
*
* </copyright>
*
*******************************************************************************/
package org.eclipse.graphiti.ui.internal.util.ui;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
/**
* A simple pop-up menu with a list from which the user can select one item.
* <p>
* The <code>show()</code> method returns false if the user cancelled the
* gesture or clicked outside the popup.
* </p>
* <p>
* The <code>getResult()</code> method returns the result which is the object
* from the content list that the user selected, or in the case of cascading
* menus, a list of the results from each popup.
*
* @noinstantiate This class is not intended to be instantiated by clients.
* @noextend This class is not intended to be subclassed by clients.
*/
public class PopupMenu {
/**
* An instance of this class can be created to add a submenu to a menu item
* in a <code>PopupMenu</code>.
*/
public static class CascadingMenu {
/** the content of the parent menu item */
private Object parentMenuItem;
/** the sub menu */
private PopupMenu subMenu;
/**
* Creates a new <code>CascadingMenu</code>.
*
* @param aParentMenuItem
* content of the parent menu item
* @param aSubMenu
* PopupMenu to be used as a submenu
*/
public CascadingMenu(Object aParentMenuItem, PopupMenu aSubMenu) {
this.parentMenuItem = aParentMenuItem;
this.subMenu = aSubMenu;
}
/**
* Gets the parentMenuItem.
*
* @return Returns the parentMenuItem.
*/
public Object getParentMenuItem() {
return parentMenuItem;
}
/**
* Gets the subMenu.
*
* @return Returns the subMenu.
*/
public PopupMenu getSubMenu() {
return subMenu;
}
}
/**
* The content of this menu. Each entry in the list becomes a menu item.
*/
private List<?> content;
/**
* Provides the text and icon for each menu item.
*/
private ILabelProvider labelProvider;
/**
* The object from the content list that the user selected. In the case of
* cascading menus, this will have multiple objects.
*/
private List<Object> resultList = new ArrayList<Object>();
private Menu menu;
/**
* Creates a new <code>PopupMenu</code>.
*
* @param aContent
* the content for the menu, each object in the list represents a
* menu item
* @param aLabelProvider
* the label provider used to provide the text for each object in
* the content list
*/
public PopupMenu(List<?> aContent, ILabelProvider aLabelProvider) {
setContent(aContent);
setLabelProvider(aLabelProvider);
}
/**
* Shows the popup menu and sets the resultList selected by the user.
*
* @param parent
* menu will be shown in this parent Control
* @return true if this succeeded, false otherwise (e.g. if the user
* cancelled the gesture).
*/
public boolean show(Control parent) {
menu = new Menu(parent);
createMenuItems(menu, this, new ArrayList<Object>());
menu.setVisible(true);
Display display = menu.getDisplay();
while (!menu.isDisposed() && menu.isVisible()) {
if (!display.readAndDispatch())
display.sleep();
}
if (!menu.isDisposed()) {
menu.dispose();
if (getResult() != null) {
return true;
}
}
return false;
}
/**
* Creates the menu items based on the content list.
*
* @param parentMenu
* the parent Menu that the menu items will be created in
* @param rootMenu
* the root level Menu
* @param resultThusFar
* List of content objects, e.g. CascadingMenu objects
*/
protected void createMenuItems(Menu parentMenu, final PopupMenu rootMenu, final List<Object> resultThusFar) {
Assert.isNotNull(getContent());
Assert.isNotNull(getLabelProvider());
for (Iterator<?> iter = getContent().iterator(); iter.hasNext();) {
Object contentObject = iter.next();
MenuItem menuItem;
if (contentObject instanceof CascadingMenu) {
PopupMenu subMenu = ((CascadingMenu) contentObject).getSubMenu();
contentObject = ((CascadingMenu) contentObject).getParentMenuItem();
List<Object> thisResult = new ArrayList<Object>(resultThusFar);
thisResult.add(contentObject);
menuItem = new MenuItem(parentMenu, SWT.CASCADE);
menuItem.setMenu(new Menu(parentMenu));
subMenu.createMenuItems(menuItem.getMenu(), rootMenu, thisResult);
} else {
menuItem = new MenuItem(parentMenu, SWT.NONE);
}
final Object fContentObject = contentObject;
menuItem.setText(getLabelProvider().getText(contentObject));
menuItem.setImage(getLabelProvider().getImage(contentObject));
menuItem.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
resultThusFar.add(fContentObject);
rootMenu.setResult(resultThusFar);
}
public void widgetDefaultSelected(SelectionEvent e) {
resultThusFar.add(fContentObject);
rootMenu.setResult(resultThusFar);
}
});
}
}
/**
* Gets the content.
*
* @return Returns the content.
*/
protected List<?> getContent() {
return content;
}
/**
* Sets the content.
*
* @param aContent
* The content of this menu. Each entry in the list becomes a
* menu item.
*/
public void setContent(List<?> aContent) {
this.content = aContent;
}
/**
* Gets the labelProvider.
*
* @return Returns the labelProvider.
*/
protected ILabelProvider getLabelProvider() {
return labelProvider;
}
/**
* Sets the labelProvider.
*
* @param aLabelProvider
* Provides the text and icon for each menu item.
*/
public void setLabelProvider(ILabelProvider aLabelProvider) {
this.labelProvider = aLabelProvider;
}
/**
* Gets the result which is the object from the content list that the user
* selected, or in the case of cascading menus, a list of the results from
* each popup.
*
* @return Returns the resultList.
*/
public Object getResult() {
if (resultList == null || resultList.isEmpty()) {
return null;
} else if (resultList.size() == 1) {
return resultList.get(0);
}
return resultList;
}
/**
* Sets the resultList.
*
* @param aResultList
* The resultList to set.
*/
protected void setResult(List<Object> aResultList) {
this.resultList = aResultList;
}
}