Invoking a command - how?

Tell us what you think about our book and report any errata. Sample chapters are available at http://www.qualityeclipse.com/

(Note: Previous Editions were called "Eclipse: Building Commercial Quality Plugins")

Moderators: Eric Clayberg, Dan Rubel

Invoking a command - how?

Postby bgruenba » Wed Jan 07, 2009 11:12 am

Let me preface this by saying that I may be barking up the wrong tree, so please correct me if I am wrong.

I'm working in Eclipse 3.4 on a new plugin. I am using the Command framework to implement most of the commands that are appropriate to the plugin that I am using. Thus, opening a view is a command in its own right.

There are times where I would like to invoke the command programmatically. For example, I have a wizard that contributes to the New wizards, and if a certain view is not open when I hit the performFinish in that wizard, I want the wizard to invoke the openView command that I have created.

Obviously, opening a view from the wizard is fairly easy - the code is the same as the code in the command for the most part - but the point with the command pattern is to make sure that all of the appropriate listeners for a command are properly advised. Thus, invoking the command will have all the handlers execute appropriately. I have read and worked through Chapter 6 and have not seen any example of doing this. I have also searched through the rest of the book for examlpes with not much luck.

The Eclipse documentation indicates that the way to do this is via the ICommandService which you can obtain by calling getService() on various objects. The following code succeeds in invoking the command:

Code: Select all
      ICommandService cmdService = (ICommandService) workbench.getService(ICommandService.class);
      Command cmd = cmdService.getCommand("plugin.commands.openView");
      ExecutionEvent event = new ExecutionEvent(cmd, new HashMap<String, String>(), this, null);
      try {
         cmd.executeWithChecks(event);
      }
      catch ...

The problem with this, though, is the creation of the ExecutionEvent object. HandlerUtil makes use of the ExecutionEvent object to determine the active workbench window. The problem is that my code does not provide this information and that is because I don't know how to provide it. As a result, HandlerUtil.getActiveWorkbenchWindow() throws an ExecutionException which has to be caught and dealt with in the handler.

The code in the handler now looks like this:
Code: Select all
      IWorkbenchWindow window = null;
      try {
         window = HandlerUtil.getActiveWorkbenchWindowChecked(event);
      }
      catch (ExecutionException e) {
         // Ignore... we expect this one. It means the event did not give us the detail we need.
      }
      
      if (window == null) {
         window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
         if (window == null) {
            return null;
         }
      }


Clearly, this is a workaround. I therefore have a couple of questions:
1) Am I barking up the wrong tree doing things this way?
2) Is there an easier way of doing this?
3) If not, where do I go to get the information on how to build the ExecutionEvent?
regards,
Bruce Gruenbaum
bgruenba
 
Posts: 4
Joined: Tue Jan 06, 2009 12:30 pm

Re: Invoking a command - how?

Postby Dan Rubel » Mon Jan 12, 2009 9:40 am

It appears that you need to construct an "application context" and pass that when constructing the ExecutionEvent.
I have not tried this, but based upon your code snippet, I think that you would want to add...
Code: Select all
IEvaluationService evalService = (IEvaluationService) workbench.getService(IEvaluationService.class);
IEvaluationContext currentState = evalService.getCurrentState();

and then pass currentState when constructing the ExecutionEvent.
Your code snippet would then look something like...
Code: Select all
ICommandService cmdService = (ICommandService) workbench.getService(ICommandService.class);
Command cmd = cmdService.getCommand("plugin.commands.openView");
IEvaluationService evalService = (IEvaluationService) workbench.getService(IEvaluationService.class);
IEvaluationContext currentState = evalService.getCurrentState();
ExecutionEvent event = new ExecutionEvent(cmd, new HashMap<String, String>(), this, currentState);
try {
   cmd.executeWithChecks(event);
}
catch ...

I'd be interested to know how this works for you.
Dan Rubel
Moderator
 
Posts: 27
Joined: Thu Oct 30, 2003 9:13 am

Re: Invoking a command - how?

Postby bgruenba » Mon Jan 12, 2009 7:01 pm

Thanks for your response, Dan.

Since I posted this question initially, I found out about the IEvaluationContext interface. The problem was that I could not find a way of creating one. So I tried doing it manually. This worked. But creating the IEvaluationContext is a pain.

Your advice above helps, but I still end up with a problem that I have not been able to workaround without modifying the IEvaluationContext.

The command gets invoked, but it fails in the handler on the call to HandlerUtil.getActiveWorkbenchWindowChecked(). I get the following stack trace:
Code: Select all
org.eclipse.core.commands.ExecutionException: No activeWorkbenchWindow found while executing net.earthlink.is.ui.bridge.commands.openAppServerExplorerView
   at org.eclipse.ui.handlers.HandlerUtil.noVariableFound(HandlerUtil.java:38)
   at org.eclipse.ui.handlers.HandlerUtil.getVariableChecked(HandlerUtil.java:87)
   at org.eclipse.ui.handlers.HandlerUtil.getActiveWorkbenchWindowChecked(HandlerUtil.java:208)
   at net.earthlink.is.ui.bridge.handlers.OpenAppServerViewHandler.execute(OpenAppServerViewHandler.java:21)
   at org.eclipse.ui.internal.handlers.HandlerProxy.execute(HandlerProxy.java:281)
   at org.eclipse.core.commands.Command.executeWithChecks(Command.java:476)
   at org.eclipse.ui.internal.handlers.HandlerService.executeCommand(HandlerService.java:178)
   at net.earthlink.is.ui.bridge.wizards.NewAppServerConnectionWizard.performFinish(NewAppServerConnectionWizard.java:55)
... rest skipped for brevity


What is interesting is that there is a much easier way of getting to the same place:
Code: Select all
final String cmdName = "net.earthlink.is.ui.bridge.commands.openAppServerExplorerView";
IHandlerService handlerService = (IHandlerService) workbench.getService(IHandlerService.class);
try {
   handlerService.executeCommand(cmdName, new Event());
}
catch...


But even with this, I still have the problem with HandlerUtil.getActiveWorkbenchWindow() call. I use the Checked version so that I get the exception. I can change the code in the command to use PlatformUI.getWorkbench().getActiveWorkbenchWindow(), but that seems like a workaround.

IEvaluationContext has a list of variables that are supposed to be set up by a call to IEvaluationService.getCurrentState(). It would seem that this code would fetch the current state, regardless of any selection, but that does not appear to be true. I am at a loss and will post this to the Eclipse forums. I think that the fact that I am in a wizard at the time means that there is no active selection and I suspect that that means that the IEvaluationService has no context to use for the call to getCurrentState().
regards,
Bruce Gruenbaum
bgruenba
 
Posts: 4
Joined: Tue Jan 06, 2009 12:30 pm


Return to Book: Eclipse Plug-Ins (3rd Edition)

Who is online

Users browsing this forum: No registered users and 1 guest