A handler can be specified with activeWhen condition using the expression language. Say for our command, we have two different handlers. One should be active when the current selection is an IFile and the other should be active when the current selection is IFolder. The expression for these would look like:
<handler
class="com.eclipse_tips.commads.SomeCommandHandler1"
commandId="com.eclipse-tips.commands.someCommand">
<activeWhen>
<with
variable="selection">
<iterate
operator="or">
<instanceof
value="org.eclipse.core.resources.IFile">
</instanceof>
</iterate>
</with>
</activeWhen>
</handler>
<handler
class="com.eclipse_tips.commads.SomeCommandHandler2"
commandId="com.eclipse-tips.commands.someCommand">
<activeWhen>
<with
variable="selection">
<iterate
operator="or">
<instanceof
value="org.eclipse.core.resources.IFolder">
</instanceof>
</iterate>
</with>
</activeWhen>
</handler>
I'll save the explanation for the expression language for a separate tip, but for now a short one line desc: the first handler will be enabled when the selection current contains at least one IFile and the second handler will be enabled when the selection contains at least one IFolder. This raises to two questions.
1) What if the selection is just an IProject?
In this case, as none of the handlers are eligible, the command is disabled. This is where the default handler, if you have provided one, would be associated with the command (and the command will be enabled).2) What if the selection contains both IFile and IFolder?
Now both the handlers are equally qualified to handle the command. But since the framework cannot pick one randomly the command is simply disabled. Even if you have provided a default handler, it won't be associated with the command, because the other two handlers are more specific than the default one.How is the "specificness" of a handler is defined? It depends on the conditions that you give in the activeWhen expression. The order is defined in the ISources class. You can go thru the complete set there, to get a glimpse of the most commonly used ones, the order from least specific to most specific is like this:
- Active Context (activeContexts)
- Active Actions Sets (activeActionSets)
- Active Shell (activeShell)
- Active Workbench Window (activeWorkbenchWindow)
- Active Editor Id (activeEditorId)
- Active Part Id (activePartId)
- Current Selection (selection)
All these things are done without even loading your handler in the memory. Even without loading your plugin!
In the previous tip, we saw how a handler is selected with the activeWhen expression, when more than one handler is declared. Now assuming a handler is selected, whether to enable the command or not, is determined by the enabledWhen expression.
In our previous example, we saw the handler that is active when the selection at least contained one IFile. Now lets we want to enable it only when the total count of the selection is 2. We can specify it as:
<handler
class="com.eclipse_tips.commads.SomeCommandHandler1"
commandId="com.eclipse-tips.commands.someCommand">
<activeWhen>
<with
variable="selection">
<iterate
operator="or">
<instanceof
value="org.eclipse.core.resources.IFile">
</instanceof>
</iterate>
</with>
</activeWhen>
<enabledWhen>
<with
variable="selection">
<count
value="2">
</count>
</with>
</enabledWhen>
</handler>
So the handler will be active and associated with the command, if the selection contains at least one IFile. Still the command will be enabled only if selection has exactly 2 elements. activeWhen and enabledWhen are similar - with respective to the expression language and lazy loading of the plugin until the command is executed. But there is small difference - your handler might be loaded iff the enabledWhen expression returns true and your plugin is already loaded. The enablement algo works this way:
- No enabledWhen specified, plugin is not loaded - command is enabled
- No enabledWhen specified, but plugin is loaded - consult handler.isEnabled() and set command accordingly
- enabledWhen specified, returns false, command is disabled (no matter plugin is loaded or not)
- enabledWhen specified, returns true, plugin is not loaded - command is enabled
- enabledWhen specified, returns true, plugin is loaded - consult handler.isEnabled() and set command accordingly
Update (31-Mar-2009): Thanks to Hiroki Kondo, a Japanese version of this blog entry is available here.
See also:
Part 1: Actions Vs Commands
Part 3: Parameters for Commands
Part 4: Misc items ...
Part 5: ISourceProvider & dynamically updating Commands
Part 6: 'toggle' & 'radio' style menu contribution
View comments