Context menu for TreeViewer based on selected node - SWT
Asked Answered
P

4

9

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.

Peregrination answered 1/6, 2011 at 21:12 Comment(0)
E
11

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.

Eckardt answered 2/6, 2011 at 13:35 Comment(2)
Yes, I am using this approach now. In my other views I created it like this only once. But my real concern was how to change the contents of the menu.Peregrination
fillContextMenu(*) is called on every menu SWT.Show event. You can change the contents of the menu every time in that method.Eckardt
H
8

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.

Honor answered 2/6, 2011 at 0:53 Comment(2)
thanks for the tips, now i'm creating the menu once and then in case of a selection, I call action.setEnabled(false). This works ok, but I did not find a setVisible method for Action. I would like to make it hidden when some other node is selected rather than graying it out. ThanksPeregrination
If you add ActionContributionItems that contain your actions, they have a setVisible(boolean) method. But you should pick either setRemoveAllWhenShown(*) or updating the visibility of the ActionContributionItems as they're different approaches.Eckardt
L
7

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 ;)

Lassiter answered 30/1, 2012 at 19:20 Comment(0)
L
0

Suppose that you know how to create Action and you are only interested in context menu following example worked for me hope this bunch of code will help you

 private void hookContextMenu() {
    MenuManager contextMenu = new MenuManager();
    contextMenu.setRemoveAllWhenShown(true);
    contextMenu.addMenuListener(new IMenuListener() {

        @Override
        public void menuAboutToShow(IMenuManager manager) {



            IStructuredSelection sSelection = (IStructuredSelection) treeViewer.getSelection();

            }
            if(selectedObject instanceof A){
            manager.add(action);
            }

        }
    });
Lorin answered 29/5, 2017 at 10:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.