You will need rudimentary experience with Eclipse plug-in development to find this post valuable.
Create an Eclipse Plug-in Project
For this example, we do not need anything fancy, just the most basic Eclipse plug-in (File -> New -> Project... -> Plug-in Project). I called my project my.project.
Declare a Menu Extension
We will declare that we are contributing a menu item in the plugin.xml. To access the menu extension point, we need to declare a plugi-in dependency on org.eclipse.ui. The extension point we are using is org.eclipse.ui.menus.
Note: we could use the "Hello, World" command contribution as a starting point, but I prefer the agglutinative to the reductive approach as a starting point.
Add a Menu Contribution
Add a menuContribution for the org.eclipse.ui.menus extension.
Set its locationURI to popup:org.eclipse.ui.popup.any?after=additions.
The scheme popup indicates that the menuContibution should appear for context menus. Other valid values are menu and toolbar.
The menu ID org.eclipse.ui.popup.any is a magic string that explains itself. If you would prefer to use resrict the popup contribution to a specific editor or view, then use its unique ID.
The query after=additions indicates that the contribution should appear after the standard IWorkbenchActionConstants.MB_ADDITIONS group. As you might guess, the placement value after might just as well be before.
Create a Dynamic Menu Contribution Node
Add a dynamic node to the menuContribution. Here we will declare the org.eclipse.ui.actions.CompoundContributionItem that will create the dynamic menu entries. For this example, I have declared the ID as my.project.myCompoundContributionItem and the class as my.project.MyCompoundContributionItem.
Create a CompoundContributionItem
Let Eclipse create my.project.MyCompoundContributionItem.java for you and set a Debug breakpoint in the getContributionItems method. We can set the ID as my.project.myCompoundContributionItem and the class as my.project.MyCompoundContributionItem.
Side-note: Debug The Menu Contribution
From the plug-in Overview page, in the Testing category, we can launch another Eclipse runtime in debug mode and trace when the getContributionItems method is called. Just set a breakpoint inside the method body, and, when the new Eclipse workbench starts, right-click anywhere in the project explorer. We have configured the dynamic menuContribution to contribute an empty array of IContributionItem to all popup menus. It's not particularly useful, but it's a start.
Declare a Command Extension
Now that we have declared an org.eclipse.ui.menus extension and added a menuContribution with dynamic content, it should be straightforward for us to declare an org.eclipse.ui.commands extension, with two nodes: one for the category, which is the group in the context menu where our commands will appear, and one for the command declaration.
I have assigned to the category the id my.project.myCategory and name My Category and to the command the id my.project.myCommand, name Do Something and categoryId my.project.myCategory.
Declare a Command Handler
Now that we have an org.eclipse.ui.commands extension, we will add a handler for this command. We just need to declare an org.eclipse.ui.handlers extension with a new handler node and the commandId declared above, my.project.myCommand.
We can create a new AbstractHandler implementation, called my.project.MyHandler that looks something like this:
package my.project;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.ui.handlers.HandlerUtil;
public class MyHandler extends AbstractHandler {
@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
MessageDialog.openInformation(
HandlerUtil.getActiveShellChecked(event), "My Handler",
"Not yet implemented");
return null;
}
}
Add a Simple CommandContributionItem
We are now going back to the MyCompoundContributionItem class to return a CommandContributionItem for the command extension above.
You may need to declare a dependency on org.eclipse.core.runtime to get a code completion for the the PlatformUI#getWorkbench method, which returns an IWorkbench. The active workbench window will suffice as our IServiceLocator. Notice in the implementation below that the label counter (the 4th Constructor parameter from the end for the CommandContributionItem) will be incremented every time a new context menu is opened. This should satisfy our simple requirement for dynamically updating the context menu label.
Similarly, we can dynamically update the icon, tooltip, etc., based on the state of the application (current selection, current perspective, etc.).
package my.project;
import java.util.Collections;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.swt.SWT;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.CompoundContributionItem;
import org.eclipse.ui.menus.CommandContributionItem;
public class MyCompoundContributionItem extends CompoundContributionItem {
private static int counter = 0;
protected IContributionItem[] getContributionItems() {
return new IContributionItem[] {
new CommandContributionItem(PlatformUI.getWorkbench().getActiveWorkbenchWindow(),
"my.project.myCommandContributionItem", "my.project.myCommand",
Collections.emptyMap(), null, null, null,
"Dynamic Menu "+ counter++, null, null, SWT.NONE)
};
}
}
Now we can Launch the Eclipse Application from the Testing section of the Overview tab, right-click a few times and watch as the menu label is updated every time a new context menu pops up!
Note: as of Ganymede (Eclipse 3.4), the above constructor for CommandContributionItem has been deprecated. For an example of the class MyCompoundContributionItem for use in Eclipse 3.4, look here.
6 comments:
for eclipse 3.4 the CompoundContributionItem would have to be like this:
public class ContributionItem1 extends CompoundContributionItem {
@Override
protected IContributionItem[] getContributionItems() {
CommandContributionItemParameter ccip = new CommandContributionItemParameter(
PlatformUI.getWorkbench().getActiveWorkbenchWindow(),
"my.project.myCommandContributionItem", "sysOutSelCommand",
CommandContributionItem.STYLE_PUSH);
return new IContributionItem[] { new CommandContributionItem(ccip) };
}
}
Hi SeuAndré,
Thanks very much for your post and your interest.
I am not clear on how your comment presents a different solution than the post linked in the last line of the blog entry (http://timezra.blogspot.com/2008/01/dynamic-labels-redux.html), aside from the CommandContributionItem.STYLE_PUSH style bit.
Could you clarify?
Thanks.
------Tim-------
oh, u'r right, sorry i did not pay attention to that last line :)
Hi SeuAndré,
No worries. Your comment indicates that I should make it clearer earlier in the post that the solution proposed is more appropriate for particular versions of Eclipse.
I always appreciate the feedback!
------Tim------
Very good your code and clear your explanations.
Thanks a lot!
Hi SeuAndre ,
I loved ur code explanation but i have a different problem if u could help.
I want to add dynamic entries to submenus on a particular type of object
example:
OBJ1->right click--->MyMenu-->Item1
-->Item2
-->Item3
and so on.......
Post a Comment