/*******************************************************************************
* Copyright (c) 2000, 2015 IBM Corporation and others.
* 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:
* IBM Corporation - initial API and implementation
* Patrick Tasse - Support JFace MenuManager
*******************************************************************************/
package org.eclipse.swt.examples.controlexample;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Decorations;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Item;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
class MenuTab extends Tab {
/* Widgets added to the "Menu Style", "MenuItem Style" and "Other" groups */
Button barButton, dropDownButton, popUpButton, noRadioGroupButton, leftToRightButton, rightToLeftButton;
Button checkButton, cascadeButton, pushButton, radioButton, separatorButton;
Button createButton, closeAllButton;
Button imagesButton, acceleratorsButton, mnemonicsButton, subMenuButton, subSubMenuButton;
Button menuManagerButton, dynamicButton;
Group menuItemStyleGroup;
/* Variables used to track the open shells */
int shellCount = 0;
Shell[] shells = new Shell[4];
/* Map used to persist actions in dynamic menus */
Map<Menu, List<IAction>> actions = new HashMap<Menu, List<IAction>>();
/* Selection listener for menu items */
SelectionListener selectionListener = new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
if (e.widget instanceof MenuItem) {
eventConsole.append("Clicked on menu item: ");
eventConsole.append(getMenuItemPath((MenuItem) e.widget));
eventConsole.append("\n");
}
}
};
/**
* Creates the Tab within a given instance of ControlExample.
*/
MenuTab(ControlExample instance) {
super(instance);
}
/**
* Handle the Create button selection event.
*
* @param event
* org.eclipse.swt.events.SelectionEvent
*/
public void createButtonSelected(SelectionEvent event) {
/*
* Remember the example shells so they can be disposed by the user.
*/
if (shellCount >= shells.length) {
Shell[] newShells = new Shell[shells.length + 4];
System.arraycopy(shells, 0, newShells, 0, shells.length);
shells = newShells;
}
int orientation = 0;
if (leftToRightButton.getSelection())
orientation |= SWT.LEFT_TO_RIGHT;
if (rightToLeftButton.getSelection())
orientation |= SWT.RIGHT_TO_LEFT;
int radioBehavior = 0;
if (noRadioGroupButton.getSelection())
radioBehavior |= SWT.NO_RADIO_GROUP;
/* Create the shell and menu(s) */
Shell shell = new Shell(SWT.SHELL_TRIM | orientation);
hookListeners(shell);
shells[shellCount] = shell;
if (barButton.getSelection()) {
if (!menuManagerButton.getSelection()) {
createMenuBar(shell, radioBehavior);
} else {
createDynamicMenuBar(shell);
}
}
if (popUpButton.getSelection()) {
if (!menuManagerButton.getSelection()) {
createPopupMenu(shell, radioBehavior);
} else {
createDynamicPopupMenu(shell);
}
}
/* Set the size, title and open the shell. */
Rectangle trim = shell.computeTrim(SWT.DEFAULT, SWT.DEFAULT, 300, 60);
shell.setSize(trim.width, trim.height);
shell.setText(ControlExample.getResourceString("Title") + shellCount);
shell.addPaintListener(new PaintListener() {
public void paintControl(PaintEvent e) {
e.gc.drawString(ControlExample.getResourceString("PopupMenuHere"), 20, 20);
}
});
shell.open();
shellCount++;
}
/**
* Close all the example shells.
*/
void closeAllShells() {
for (int i = 0; i < shellCount; i++)
if (shells[i] != null & !shells[i].isDisposed())
shells[i].dispose();
shellCount = 0;
}
/**
* Creates the "Control" group.
*/
void createControlGroup() {
/*
* Create the "Control" group. This is the group on the right half of each example tab. For MenuTab, it consists
* of the Menu style group, the MenuItem style group and the 'other' group.
*/
controlGroup = new Group(tabFolderPage, SWT.NONE);
controlGroup.setLayout(new GridLayout(2, true));
controlGroup.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL));
controlGroup.setText(ControlExample.getResourceString("Parameters"));
/* Create a group for the menu style controls */
styleGroup = new Group(controlGroup, SWT.NONE);
styleGroup.setLayout(new GridLayout());
styleGroup.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL));
styleGroup.setText(ControlExample.getResourceString("Menu_Styles"));
/* Create a group for the menu item style controls */
menuItemStyleGroup = new Group(controlGroup, SWT.NONE);
menuItemStyleGroup.setLayout(new GridLayout());
menuItemStyleGroup.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL));
menuItemStyleGroup.setText(ControlExample.getResourceString("MenuItem_Styles"));
/* Create a group for the 'other' controls */
otherGroup = new Group(controlGroup, SWT.NONE);
otherGroup.setLayout(new GridLayout());
otherGroup.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL));
otherGroup.setText(ControlExample.getResourceString("Other"));
}
/**
* Creates the "Control" widget children.
*/
void createControlWidgets() {
/* Create the menu style buttons */
barButton = new Button(styleGroup, SWT.CHECK);
barButton.setText("SWT.BAR");
dropDownButton = new Button(styleGroup, SWT.CHECK);
dropDownButton.setText("SWT.DROP_DOWN");
popUpButton = new Button(styleGroup, SWT.CHECK);
popUpButton.setText("SWT.POP_UP");
noRadioGroupButton = new Button(styleGroup, SWT.CHECK);
noRadioGroupButton.setText("SWT.NO_RADIO_GROUP");
leftToRightButton = new Button(styleGroup, SWT.RADIO);
leftToRightButton.setText("SWT.LEFT_TO_RIGHT");
leftToRightButton.setSelection(true);
rightToLeftButton = new Button(styleGroup, SWT.RADIO);
rightToLeftButton.setText("SWT.RIGHT_TO_LEFT");
/* Create the menu item style buttons */
cascadeButton = new Button(menuItemStyleGroup, SWT.CHECK);
cascadeButton.setText("SWT.CASCADE");
checkButton = new Button(menuItemStyleGroup, SWT.CHECK);
checkButton.setText("SWT.CHECK");
pushButton = new Button(menuItemStyleGroup, SWT.CHECK);
pushButton.setText("SWT.PUSH");
radioButton = new Button(menuItemStyleGroup, SWT.CHECK);
radioButton.setText("SWT.RADIO");
separatorButton = new Button(menuItemStyleGroup, SWT.CHECK);
separatorButton.setText("SWT.SEPARATOR");
/* Create the 'other' buttons */
imagesButton = new Button(otherGroup, SWT.CHECK);
imagesButton.setText(ControlExample.getResourceString("Images"));
acceleratorsButton = new Button(otherGroup, SWT.CHECK);
acceleratorsButton.setText(ControlExample.getResourceString("Accelerators"));
mnemonicsButton = new Button(otherGroup, SWT.CHECK);
mnemonicsButton.setText(ControlExample.getResourceString("Mnemonics"));
subMenuButton = new Button(otherGroup, SWT.CHECK);
subMenuButton.setText(ControlExample.getResourceString("SubMenu"));
subSubMenuButton = new Button(otherGroup, SWT.CHECK);
subSubMenuButton.setText(ControlExample.getResourceString("SubSubMenu"));
menuManagerButton = new Button(otherGroup, SWT.CHECK);
menuManagerButton.setText(ControlExample.getResourceString("MenuManager"));
dynamicButton = new Button(otherGroup, SWT.CHECK);
dynamicButton.setText(ControlExample.getResourceString("Dynamic"));
/* Create the "create" and "closeAll" buttons (and a 'filler' label to place them) */
new Label(controlGroup, SWT.NONE);
createButton = new Button(controlGroup, SWT.NONE);
createButton.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END));
createButton.setText(ControlExample.getResourceString("Create_Shell"));
closeAllButton = new Button(controlGroup, SWT.NONE);
closeAllButton.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING));
closeAllButton.setText(ControlExample.getResourceString("Close_All_Shells"));
/* Add the listeners */
createButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
createButtonSelected(e);
}
});
closeAllButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
closeAllShells();
}
});
subMenuButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
subSubMenuButton.setEnabled(subMenuButton.getSelection());
}
});
menuManagerButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
dynamicButton.setEnabled(menuManagerButton.getSelection());
dynamicButton.setSelection(menuManagerButton.getSelection());
noRadioGroupButton.setEnabled(!menuManagerButton.getSelection());
}
});
/* Set the default state */
barButton.setSelection(true);
dropDownButton.setSelection(true);
popUpButton.setSelection(true);
cascadeButton.setSelection(true);
checkButton.setSelection(true);
pushButton.setSelection(true);
radioButton.setSelection(true);
separatorButton.setSelection(true);
subSubMenuButton.setEnabled(subMenuButton.getSelection());
dynamicButton.setEnabled(menuManagerButton.getSelection());
}
/* Create menu bar. */
void createMenuBar(Shell shell, int radioBehavior) {
Menu menuBar = new Menu(shell, SWT.BAR | radioBehavior);
shell.setMenuBar(menuBar);
hookListeners(menuBar);
if (dropDownButton.getSelection() && cascadeButton.getSelection()) {
/* Create cascade button and drop-down menu in menu bar. */
MenuItem item = new MenuItem(menuBar, SWT.CASCADE);
item.setText(getMenuItemText("Cascade"));
if (imagesButton.getSelection())
item.setImage(instance.images[ControlExample.ciOpenFolder]);
hookListeners(item);
Menu dropDownMenu = new Menu(shell, SWT.DROP_DOWN | radioBehavior);
item.setMenu(dropDownMenu);
hookListeners(dropDownMenu);
/* Create various menu items, depending on selections. */
createMenuItems(dropDownMenu, radioBehavior, subMenuButton.getSelection(), subSubMenuButton.getSelection());
}
}
/* Create dynamic menu bar using JFace MenuManager. */
void createDynamicMenuBar(Shell shell) {
MenuManager menuManager = new HookedMenuManager();
final Menu menuBar = menuManager.createMenuBar((Decorations) shell);
shell.setMenuBar(menuBar);
hookListeners(menuBar);
if (dropDownButton.getSelection() && cascadeButton.getSelection()) {
/* Create cascade button and drop-down menu in menu bar. */
MenuManager dropDownMenuManager = new HookedMenuManager(getMenuItemText("Cascade"), instance.images[ControlExample.ciOpenFolder]);
dropDownMenuManager.setRemoveAllWhenShown(dynamicButton.getSelection());
menuManager.add(dropDownMenuManager);
if (dynamicButton.getSelection()) {
dropDownMenuManager.addMenuListener(new IMenuListener() {
public void menuAboutToShow(IMenuManager manager) {
/* Create various menu manager contribution items, depending on selections. */
createMenuContributionItems(manager, menuBar, 0, subMenuButton.getSelection(), subSubMenuButton.getSelection());
}
});
} else {
createMenuContributionItems(dropDownMenuManager, menuBar, 0, subMenuButton.getSelection(), subSubMenuButton.getSelection());
}
menuManager.update(false);
}
}
/* Create pop-up menu. */
void createPopupMenu(Shell shell, int radioBehavior) {
Menu popUpMenu = new Menu(shell, SWT.POP_UP | radioBehavior);
shell.setMenu(popUpMenu);
hookListeners(popUpMenu);
/* Create various menu items, depending on selections. */
createMenuItems(popUpMenu, radioBehavior, subMenuButton.getSelection(), subSubMenuButton.getSelection());
}
/* Create dynamic pop-up menu using JFace MenuManager. */
void createDynamicPopupMenu(Shell shell) {
MenuManager menuManager = new HookedMenuManager();
menuManager.setRemoveAllWhenShown(dynamicButton.getSelection());
final Menu popupMenu = menuManager.createContextMenu(shell);
shell.setMenu(popupMenu);
hookListeners(popupMenu);
if (dynamicButton.getSelection()) {
menuManager.addMenuListener(new IMenuListener() {
public void menuAboutToShow(IMenuManager manager) {
/* Create various menu items, depending on selections. */
createMenuContributionItems(manager, popupMenu, 0, subMenuButton.getSelection(), subSubMenuButton.getSelection());
}
});
} else {
createMenuContributionItems(menuManager, popupMenu, 0, subMenuButton.getSelection(), subSubMenuButton.getSelection());
}
}
/* Create various menu items, depending on selections. */
void createMenuItems(Menu menu, int radioBehavior, boolean createSubMenu, boolean createSubSubMenu) {
MenuItem item;
if (pushButton.getSelection()) {
item = new MenuItem(menu, SWT.PUSH);
item.setText(getMenuItemText("Push"));
if (acceleratorsButton.getSelection())
item.setAccelerator(SWT.MOD1 + SWT.MOD2 + 'P');
if (imagesButton.getSelection())
item.setImage(instance.images[ControlExample.ciClosedFolder]);
hookListeners(item);
item.addSelectionListener(selectionListener);
}
if (separatorButton.getSelection())
new MenuItem(menu, SWT.SEPARATOR);
if (checkButton.getSelection()) {
item = new MenuItem(menu, SWT.CHECK);
item.setText(getMenuItemText("Check"));
if (acceleratorsButton.getSelection())
item.setAccelerator(SWT.MOD1 + SWT.MOD2 + 'C');
if (imagesButton.getSelection())
item.setImage(instance.images[ControlExample.ciOpenFolder]);
hookListeners(item);
item.addSelectionListener(selectionListener);
}
if (radioButton.getSelection()) {
item = new MenuItem(menu, SWT.RADIO);
item.setText(getMenuItemText("1Radio"));
if (acceleratorsButton.getSelection())
item.setAccelerator(SWT.MOD1 + SWT.MOD2 + '1');
if (imagesButton.getSelection())
item.setImage(instance.images[ControlExample.ciTarget]);
item.setSelection(true);
hookListeners(item);
item.addSelectionListener(selectionListener);
item = new MenuItem(menu, SWT.RADIO);
item.setText(getMenuItemText("2Radio"));
if (acceleratorsButton.getSelection())
item.setAccelerator(SWT.MOD1 + SWT.MOD2 + '2');
if (imagesButton.getSelection())
item.setImage(instance.images[ControlExample.ciTarget]);
hookListeners(item);
item.addSelectionListener(selectionListener);
}
if (createSubMenu && cascadeButton.getSelection()) {
/* Create cascade button and drop-down menu for the sub-menu. */
item = new MenuItem(menu, SWT.CASCADE);
item.setText(getMenuItemText("Cascade"));
if (imagesButton.getSelection())
item.setImage(instance.images[ControlExample.ciOpenFolder]);
hookListeners(item);
Menu subMenu = new Menu(menu.getShell(), SWT.DROP_DOWN | radioBehavior);
item.setMenu(subMenu);
hookListeners(subMenu);
item.addSelectionListener(selectionListener);
createMenuItems(subMenu, radioBehavior, createSubSubMenu, false);
}
}
/* Create various menu manager contribution items, depending on selections. */
void createMenuContributionItems(IMenuManager menu, final Menu rootMenu, final int depth, final boolean createSubMenu, final boolean createSubSubMenu) {
if (pushButton.getSelection()) {
/* Creating a new action instance will force the old MenuItem to be disposed */
Action action = new Action(getMenuItemText("Push"), IAction.AS_PUSH_BUTTON) {};
if (acceleratorsButton.getSelection()) {
action.setAccelerator(SWT.MOD1 + SWT.MOD2 + 'P');
}
if (imagesButton.getSelection()) {
action.setImageDescriptor(ImageDescriptor.createFromImage(instance.images[ControlExample.ciClosedFolder]));
}
menu.add(action);
}
if (separatorButton.getSelection())
menu.add(new Separator());
if (checkButton.getSelection()) {
IAction action = getAction(rootMenu, depth, getMenuItemText("Check"), IAction.AS_CHECK_BOX, false,
SWT.MOD1 + SWT.MOD2 + 'C', ImageDescriptor.createFromImage(instance.images[ControlExample.ciOpenFolder]));
menu.add(action);
}
if (radioButton.getSelection()) {
IAction action = getAction(rootMenu, depth, getMenuItemText("1Radio"), IAction.AS_RADIO_BUTTON, true,
SWT.MOD1 + SWT.MOD2 + '1', ImageDescriptor.createFromImage(instance.images[ControlExample.ciTarget]));
menu.add(action);
action = getAction(rootMenu, depth, getMenuItemText("2Radio"), IAction.AS_RADIO_BUTTON, false,
SWT.MOD1 + SWT.MOD2 + '2', ImageDescriptor.createFromImage(instance.images[ControlExample.ciTarget]));
menu.add(action);
}
if (createSubMenu && cascadeButton.getSelection()) {
/* Create cascade button and drop-down menu for the sub-menu. */
MenuManager subMenuManager = new HookedMenuManager(getMenuItemText("Cascade"), instance.images[ControlExample.ciOpenFolder]);
subMenuManager.setRemoveAllWhenShown(dynamicButton.getSelection());
menu.add(subMenuManager);
if (dynamicButton.getSelection()) {
subMenuManager.addMenuListener(new IMenuListener() {
public void menuAboutToShow(IMenuManager manager) {
/* Create various menu items, depending on selections. */
createMenuContributionItems(manager, rootMenu, depth + 1, createSubSubMenu, false);
}
});
} else {
createMenuContributionItems(subMenuManager, rootMenu, depth + 1, createSubSubMenu, false);
}
}
}
/*
* Creates an action and stores it in a map to preserve the action state.
* Returns the stored action if it already exists in the map for the same
* root menu, depth, text, and style.
*/
private IAction getAction(Menu rootMenu, int depth, String text, int style, boolean checked, int keycode, ImageDescriptor image) {
List<IAction> actionList = actions.get(rootMenu);
if (actionList == null) {
actionList = new ArrayList<IAction>();
actions.put(rootMenu, actionList);
rootMenu.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
actions.remove(e.widget);
}
});
}
for (IAction action : actionList) {
if (action.getText().equals(text) && action.getStyle() == style) {
if (depth-- == 0) {
return action;
}
}
}
Action action = new Action(text, style) {};
actionList.add(action);
if (checked) {
action.setChecked(checked);
}
if (acceleratorsButton.getSelection()) {
action.setAccelerator(keycode);
}
if (imagesButton.getSelection()) {
action.setImageDescriptor(image);
}
return action;
}
String getMenuItemText(String item) {
boolean cascade = item.equals("Cascade");
boolean mnemonic = mnemonicsButton.getSelection();
boolean accelerator = acceleratorsButton.getSelection();
char acceleratorKey = item.charAt(0);
if (mnemonic && accelerator && !cascade)
return ControlExample.getResourceString(item + "WithMnemonic") + "\tCtrl+Shift+" + acceleratorKey;
if (accelerator && !cascade)
return ControlExample.getResourceString(item) + "\tCtrl+Shift+" + acceleratorKey;
if (mnemonic)
return ControlExample.getResourceString(item + "WithMnemonic");
return ControlExample.getResourceString(item);
}
public String getMenuItemPath(MenuItem menuItem) {
StringBuilder sb = new StringBuilder(menuItem.getText());
if ((menuItem.getStyle() & SWT.SEPARATOR) != 0) {
sb.append("|");
}
Menu menu = menuItem.getParent();
while (menu != null) {
MenuItem item = menu.getParentItem();
if (item != null) {
sb.insert(0, item.getText() + " > ");
} else if ((menu.getStyle() & SWT.BAR) != 0) {
sb.insert(0, "BAR > ");
} else if ((menu.getStyle() & SWT.POP_UP) != 0) {
sb.insert(0, "POP_UP > ");
}
menu = menu.getParentMenu();
}
return sb.toString();
}
/**
* Gets the text for the tab folder item.
*/
String getTabText() {
return "Menu";
}
/* Menu manager that hooks listeners to its widgets as they are created */
private class HookedMenuManager extends MenuManager {
private Image image;
public HookedMenuManager() {
this(null, null);
}
public HookedMenuManager(String text, Image image) {
super(text);
this.image = image;
}
@Override
protected void doItemFill(IContributionItem ci, int index) {
super.doItemFill(ci, index);
Item item = getMenuItem(index);
if (imagesButton.getSelection() && ci instanceof HookedMenuManager) {
item.setImage(((HookedMenuManager) ci).image);
}
hookListeners(item);
if (item instanceof MenuItem) {
MenuItem menuItem = (MenuItem) item;
Menu menu = menuItem.getMenu();
if (menu != null) {
hookListeners(menu);
}
menuItem.addSelectionListener(selectionListener);
}
}
}
}