I need to create a context menu for a TreeViewer in an Eclipse plugin project. But, the menu should not contain constant items, they should vary depending on the type of the node that is selected. For example, my treeViewer has the following hierarchy:
Node A
|
--Node B
|
--Node C
For node A - I want to show a menu with an action, but for nodes B and C I don't want to show anything (no menu). I managed to create the menu for node A, but then I can't get rid of it when some other type of node is selected. My code looks like:
treeViewer.addSelectionChangedListener(
new ISelectionChangedListener(){
public void selectionChanged(SelectionChangedEvent event) {
if(event.getSelection() instanceof IStructuredSelection) {
IStructuredSelection selection = (IStructuredSelection)event.getSelection();
Object o = selection.getFirstElement();
MenuManager menuMgr = new MenuManager();
if (o instanceof NodeA){
Menu menu = menuMgr.createContextMenu(treeViewer.getControl());
treeViewer.getControl().setMenu(menu);
getSite().registerContextMenu(menuMgr, treeViewer);
menuMgr.add(new SomeAction());
}else {
//what ?
}
}
}
}
);
On the else branch I tried to call dispose()
,removeAll()
on the MenuManager...nothing works!
Any help is appreciated, thanks.
As @jeeeyul mentioned, you should only create one MenuManager to use within your view.
You can use New>Plug-in Project and the view template to get an example of a context menu in a view using a viewer, but basically in your createPartControl(Composite)
method you would hook up your context manager.
MenuManager menuMgr = new MenuManager();
menuMgr.setRemoveAllWhenShown(true);
menuMgr.addMenuListener(new IMenuListener() {
public void menuAboutToShow(IMenuManager manager) {
SampleView.this.fillContextMenu(manager);
}
});
Menu menu = menuMgr.createContextMenu(viewer.getControl());
viewer.getControl().setMenu(menu);
getSite().registerContextMenu(menuMgr, viewer);
Your fillContextMenu(MenuManager)
method will have access to your viewer, so you can get the current selection from that. You can add whatever actions you want, even re-add actions after updating them with the current selection.
The registerContextMenu(*)
call allows extension points like org.eclipse.ui.popupMenus and org.eclipse.ui.menus to contribute items to your context menu.
Just use single Menu Manager. Do not make Menu Manager dynamically.
in theory, It's possible you tried, but it's inefficient and it's not general way.
Just make a Menu Manager and add all actions which you needs.
when selection has been changed, call Action#setVisible(true|false)to hide or show menu items. You can also use Action#setEnable to enable/disable menu item.
ps. Menu Manager is not a menu GUI(likes TreeViewer is a not tree)
It contributes Actions(business logic) to Menu(SWT). And It also manage visibility and enablement. We call this Contribution Manager. We can create a SWT menu very easy with this. (even we don't know about SWT, we just have to know only our business logic:Action) It's fundamental idea in JFace.
When you add an action into manu manager, action will be wrapped with ActionContributionItem. It hooks action's state to update UI(visibility, enablement for menu, button, toolbar and so on). It also hooks UI to launch action when it pressed.
If you are new to eclipse, It is easy to confuse role of SWT and JFace.
Thats the way I do it:
MenuManager menuMgr = new MenuManager();
Menu menu = menuMgr.createContextMenu(viewer.getControl());
menuMgr.addMenuListener(new IMenuListener() {
@Override
public void menuAboutToShow(IMenuManager manager) {
// IWorkbench wb = PlatformUI.getWorkbench();
// IWorkbenchWindow win = wb.getActiveWorkbenchWindow();
if (viewer.getSelection().isEmpty()) {
return;
}
if (viewer.getSelection() instanceof IStructuredSelection) {
IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
Node object = (Node)selection.getFirstElement();
if (object.getModel() instanceof NodeA) {
manager.add(new Action();
} else if (object.getModel() instanceof NodeB) {
manager.add(new OtherAction());
}
}
}
});
menuMgr.setRemoveAllWhenShown(true);
viewer.getControl().setMenu(menu);
I hope this helps ;)
It is important to set removeAllWhenShown property of menu manager to false, in order to hide all the other nodes actions ;)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With