Imagine you already have a ContextMenuProvider setup in your GEF editor but you would like to have multiple levels of actions, grouping elements together. This is one of the elements we recently had to accomplish in jUCMNav and since the we couldn’t easily find sample code on Google, we thought it would be nice to share this code with you.
1: package seg.jUCMNav.actions;
2:
3: import org.eclipse.jface.action.Action;
4: import org.eclipse.jface.action.IAction;
5: import org.eclipse.jface.action.IMenuCreator;
6: import org.eclipse.jface.resource.ImageDescriptor;
7: import org.eclipse.swt.SWT;
8: import org.eclipse.swt.events.SelectionEvent;
9: import org.eclipse.swt.events.SelectionListener;
10: import org.eclipse.swt.widgets.Control;
11: import org.eclipse.swt.widgets.Menu;
12: import org.eclipse.swt.widgets.MenuItem;
13:
14: /**
15: * This action contains other actions and helps create another level of
16: * contextual menus.
17: *
18: * @author jkealey
19: *
20: */
21: public class SubmenuAction extends Action implements SelectionListener
22: {
23: // / Who to inform when this action is fired (meaning display the submenu)
24: private SelectionListener actionInstance;
25:
26: // the list of actions that are contained within this action
27: private IAction[] actions;
28:
29: // should we hide the disabled ones (if not, they will appear as grayed out)
30: private boolean hideDisabled;
31:
32: /***
33: * Create a submenu.
34: *
35: * @param subactions
36: * the actions that are contained within
37: * @param text
38: * the container's textual label
39: * @param toolTip
40: * the container's tooltip
41: * @param descriptor
42: * the container's image descriptor
43: * @param hideDisabledActions
44: * should we hide the disabled ones (if not, they will appear as
45: * grayed out)
46: */
47: public SubmenuAction(IAction[] subactions, String text, String toolTip, ImageDescriptor descriptor, boolean hideDisabledActions)
48: {
49: // indicate that this is a secondary fly-out menu.
50: super("", IAction.AS_DROP_DOWN_MENU);
51:
52: this.actionInstance = this;
53: this.actions = subactions;
54: this.hideDisabled = hideDisabledActions;
55:
56: setText(text);
57: setToolTipText(toolTip);
58: setImageDescriptor(descriptor);
59:
60: // the secondayr menu logic
61: setMenuCreator(new IMenuCreator()
62: {
63: public Menu getMenu(Control parent)
64: {
65: // this would be used outside of a menu. not useful for us.
66: return null;
67: }
68:
69: public Menu getMenu(Menu parent)
70: {
71: // create a submenu
72: Menu menu = new Menu(parent);
73: // fill it with our actions
74: for (int i = 0; i < actions.length; i++)
75: {
76: // skip the disabled ones if necessary (or null actions)
77: if (actions[i] == null || !actions[i].isEnabled() && hideDisabled)
78: continue;
79:
80: // create the submenu item
81: MenuItem item = new MenuItem(menu, SWT.NONE);
82:
83: // memorize the index
84: item.setData(new Integer(i));
85:
86: // identify it
87: item.setText(actions[i].getText());
88:
89: // create its image
90: if (actions[i].getImageDescriptor() != null)
91: item.setImage(actions[i].getImageDescriptor().createImage());
92:
93: // inform us when something is selected.
94: item.addSelectionListener(actionInstance);
95: }
96: return menu;
97: }
98:
99: public void dispose()
100: {
101: }
102: });
103:
104: }
105:
106: /**
107: * Returns how many items are enabled in the flyout. Useful to hide the
108: * submenu when none are enabled.
109: *
110: * @return the number of currently enabled menu items.
111: */
112: public int getActiveOperationCount()
113: {
114: int operationCount = 0;
115: for (int i = 0; i < actions.length; i++)
116: operationCount += actions[i] != null && actions[i].isEnabled() ? 1 : 0;
117:
118: return operationCount;
119: }
120:
121: /**
122: * Runs the default action
123: */
124: public void run()
125: {
126: actions[0].run();
127: }
128:
129: /**
130: * Runs the default action
131: */
132: public void widgetDefaultSelected(SelectionEvent e)
133: {
134: actions[0].run();
135: }
136:
137: /**
138: * Called when an item in the drop-down menu is selected. Runs the
139: * associated run() method
140: */
141: public void widgetSelected(SelectionEvent e)
142: {
143: // get the index from the data and run that action.
144: actions[((Integer) (((MenuItem) (e.getSource())).getData())).intValue()].run();
145: }
146: }
1: public class UrnContextMenuProvider extends ContextMenuProvider {
2:
3: private ActionRegistry actionRegistry;
4: /**
5: * @param viewer
6: * @param registry
7: * has to be passed in case we don't want to use the action registry used in the viewer. [is this bad coding?]
8: */
9: public UrnContextMenuProvider(EditPartViewer viewer, ActionRegistry registry) {
10: super(viewer);
11: setActionRegistry(registry);
12: }
13:
14: /**
15: *
16: * @return the action registry used by the context menu provider.
17: */
18: private ActionRegistry getActionRegistry() {
19: return actionRegistry;
20: }
21:
22: /**
23: *
24: * @param registry
25: * the action registry used by the context menu provider.
26: */
27: private void setActionRegistry(ActionRegistry registry) {
28: actionRegistry = registry;
29: }
30:
31:
32: /**
33: * Looks up a set of actions in the action registry. If they are enabled, adds them to the correct groups.
34: */
35: public void buildContextMenu(IMenuManager manager) {
36: GEFActionConstants.addStandardActionGroups(manager);
37:
38: // regular action
39: IAction action = getActionRegistry().getAction(AddLabelAction.ADDLABEL);
40: if (action.isEnabled())
41: manager.appendToGroup(GEFActionConstants.GROUP_REST, action);
42:
43: // compound action
44: IAction[] actions = new IAction[13];
45: actions[0] = getActionRegistry().getAction(AddOrForkAction.ADDORFORK);
46: actions[1] = getActionRegistry().getAction(AddAndForkAction.ADDANDFORK);
47: actions[2] = getActionRegistry().getAction(AddOrJoinAction.ADDORJOIN);
48: actions[3] = getActionRegistry().getAction(AddAndJoinAction.ADDANDJOIN);
49:
50: SubmenuAction submenu = new SubmenuAction(actions, "Path Operations", "Path operations", actions[0].getImageDescriptor(), true);
51: if (submenu.getActiveOperationCount()>0)
52: manager.appendToGroup(GEFActionConstants.GROUP_REST, submenu);
53:
54: // ... add other actions ...
55: }
56: }