Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Eclipse 4 » Removing/adding context menu entries based on current selection
Removing/adding context menu entries based on current selection [message #895776] Mon, 16 July 2012 00:20 Go to next message
brian sar is currently offline brian sarFriend
Messages: 1
Registered: July 2012
Junior Member
In a plugin I am dynamically adding a Part with a tree in it(representing a small subset of the file system) and a MPopupMenu for the tree via a processor. What I would like, is, if a user right-clicks on a tree element, e.g. Folder, I would like to show a different context menu then if he/she clicks on a File item. I need some complex logic to handle all possible combinations. I found that to achieve something like this I have to use core expressions. If I understood correctly, the best solution is to use a property tester, since I need quite some code to handle all the combination. I can not manage to wire up core expression programmatically.

Here is my current code. Everything works, expect, I would need a hook which gets called before a context menu shows up.

private void registerPopup(final MPart part, final MApplication app) {
	final MCommand command = MCommandsFactory.INSTANCE.createCommand();
	command.setCommandName("tesadsa");
	command.setElementId("testet2t");
	app.getCommands().add(command);

	final MHandler handler = MCommandsFactory.INSTANCE.createHandler();
	handler.setContributorURI("platform:/plugin/"
			+ FrameworkUtil.getBundle(this.getClass()).getSymbolicName());
	handler.setContributionURI("bundleclass://"
			+ FrameworkUtil.getBundle(this.getClass()).getSymbolicName()
			+ "/" + WorkspacePopupHook.class.getName());
	handler.setCommand(command);
	app.getHandlers().add(handler);

	final MCoreExpression coreExpression = MUiFactory.INSTANCE
			.createCoreExpression();
	// final Expression true1 = AlwaysEnabledExpression.TRUE;
	// coreExpression.setCoreExpression(new WorkspaceExpression(null));
	// coreExpression.setCoreExpression(true1);
	// final OrExpression o = new OrExpression();
	// final IConfigurationElement config = new
	// ThirdLevelConfigurationElementHandle(
	// null, 0);
	// try {
	// final PropertyTesterDescriptor p = new PropertyTesterDescriptor(
	// config);
	// } catch (final CoreException e) {
	// e.printStackTrace();
	// }

	final MHandledMenuItem handledMenuItem = MMenuFactory.INSTANCE
			.createHandledMenuItem();
	handledMenuItem.setLabel("test");
	handledMenuItem.setCommand(command);
	//handledMenuItem.setVisibleWhen(coreExpression);

	final MPopupMenu popupMenu = MMenuFactory.INSTANCE.createPopupMenu();
	popupMenu.setElementId("testid");
	popupMenu.setLabel("test2");
	popupMenu.getChildren().add(handledMenuItem);

	part.getMenus().add(popupMenu);
}

If I remove this comment
//handledMenuItem.setVisibleWhen(coreExpression);

it wont work anymore, I guess the default value for MCoreExpression is always false. So if this is the right way to do this, how can I instantiate PropertyTesterDescriptor since it needs an implementation of IConfigurationElement object which I don`t know how to instantiate. I also tried to define a core expression as an extension point and then get it through EModelService
final List findElements = mService.findElements(app, null,MCoreExpression.class, Collections.EMPTY_LIST);

with no success.

Thanks in advance.
Re: Removing/adding context menu entries based on current selection [message #895825 is a reply to message #895776] Mon, 16 July 2012 08:29 Go to previous messageGo to next message
Phill Perryman is currently offline Phill PerrymanFriend
Messages: 214
Registered: July 2009
Senior Member
You could revert to the jface context menu. In this way you dynamically build the menu when required. The actions (InvoiceAction as below) must implement org.eclipse.jface.action.Action. This way you can use whatever java code to decide if menu items are added or not. The example below is much simplified from the actual decision required in my case in which I base on the current internal state of the selected object so I would have required a property tester. In my case some of the menu items are also used in other places as normal menu handlers I extended the Action class to provide a bridge so a handler can also be an Action (see below)

MenuManager menuMgr = new MenuManager("#QuoteItemTree"); //$NON-NLS-1$
menuMgr.setRemoveAllWhenShown(true);
menuMgr.addMenuListener(new IMenuListener() {
@Override
public void menuAboutToShow(IMenuManager manager) {
IStructuredSelection selection = (IStructuredSelection)treeViewer.getSelection();
Object firstElement = selection.getFirstElement();
if (firstElement instanceof InvoiceAddress)
manager.add(new InvoiceAction(firstElement, InvoiceAction.LABEL));
if (.......)
manager.add(...);
}
});

treeViewer.getControl().setMenu(menuMgr.createContextMenu(treeViewer.getControl()));

The action class
public class InvoiceAction extends BaseAction {

public static final String LABEL = "Invoice Popup Action";

public InvoiceAction() {
super();
}

public InvoiceAction(Object selection, String label) {
super(selection, label);
}

@Override
public void execute(Object selected) {
Msg.infoMessage(LABEL + ":" + selection);
StatusBar.setStatusMessage(LABEL + ":" + selection);
}

}

The base action class can either be run as a handler in which case the update selection method will update the current selection or it can be constructed as an Action which will set the current selection via the constructor. The Action will call the run method so I annotate that with the @Execute so the handler calls the same method. Most of the menu items are specific to this menu so I just implement Action directly.

public abstract class BaseAction extends Action {

protected Object selection;

public BaseAction(Object selection, String label) {
super(label);
this.selection = selection;
}

public BaseAction() {
super();
}

@Execute
@Override
public void run() {
execute(selection);
}

@Inject
void updateSelection(
@Optional @javax.inject.Named(IServiceConstants.ACTIVE_SELECTION) Object object) {
if (object instanceof StructuredSelection) {
StructuredSelection sel = (StructuredSelection) object;
selection = sel.getFirstElement();
}
}

public abstract void execute(Object selected);


}
Re: Removing/adding context menu entries based on current selection [message #895838 is a reply to message #895776] Mon, 16 July 2012 09:13 Go to previous message
Christoph Keimel is currently offline Christoph KeimelFriend
Messages: 386
Registered: December 2010
Location: Germany
Senior Member
I have used the following approach, which works well when you have a definit number of possible combinations of commands in the context menu:

tree.addMenuDetectListener(new MenuDetectListener() {
	@Override
	public void menuDetected(MenuDetectEvent e) {
		IStructuredSelection selection = viewer.getStructuredSelection();
		if (selection.isEmpty())
			return;
		
		String id = null;
		Object obj = selection.getFirstElement();
		... set id depending on selected object ...
		
		if (id == null)
			return;
		MPopupMenu menu = menuService.registerContextMenu(tree, id);
	}
});


This way, you could either define multiple PopupMenu's in the e4xmi or you can create them with a processor.
Previous Topic:Programmatically detach a view
Next Topic:'simple' has been deprecated: renamed as swt-simple
Goto Forum:
  


Current Time: Fri Dec 19 08:47:03 GMT 2014

Powered by FUDForum. Page generated in 0.02589 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software