This is the third part of my blog series on the Eclipse Commands framework. Please see Part One for an outline of topics covered in the various blogs.
Limiting visibility of Commands
A powerful feature of the Commands framework is that you can declare in the plugin.xml when a Command should be visible (or rather when specific menu contributions should be visible) and when it should be enabled. This is done by using what is called core expressions.
Simple visibleWhen definition
Let us take a simple example first: we want to limit the Annotate eBook command (from the example in Part Two: Quick Review) to only show in the context menu if one item is selected in the view. If no item is selected, or more than one, it must not appear in the menu.
We have now set up the context-menu contribution to only show the Annotate command when one and only one item in the view is selected. That was not so difficult, was it? I remember spending hours on creating nice selection behaviour helper classes for IActionDelegate-based frameworks, and still not getting the initial visibility or enabling of the actions in the menus right, due to constraints with that approach.
The menu contributions extension in the plugin.xml now looks like:
|
Expression Definitions
Before I delve more deeply into even more interesting visibleWhen capabilities, first a very nifty tip on core expressions: it is possible to declare a specific expression definition, and then just refer to that definition from your visibleWhen, activeWhen, etc elements.
We do this with the org.eclipse.core.expressions.definitions extension. To define an expression that checks that only one item is selected:
You might have noticed it is the same steps as those followed for a simple visibleWhen definition above.
For those who rather do it directly in the plugin.xml, here is the org.eclipse.core.expressions.definitions extension declaration:
|
How do I use the expression definition?
What do you gain with first defining an expression? Well, you can reuse this definition in multiple places in your plugin.xml if you need the same expression, whether it is for a visibleWhen, activeWhen or enabledWhen declaration.
To replace our expression for our context menu contribution with the definition, you simply do the following:
If you run the application now, it should still behave the same as before we used our own definition, but now we are ready for a much more complex playing field. Underneath is a screenshot of how the extension declarations should look in the Plugin Editor.

To infinity and beyond: the power of expressions
We have seen a very basic expression up to now. You should have seen a number of other possible items to choose from when you selected New -> with in the steps above. I list them below. These can all be used to build up complex expressions that gets evaluated at runtime to determine whether a specific menu contribution should be visible or not, if used in conjunction with a visibleWhen element.

| Element | Description |
|---|---|
| adapt | Use to adapt the object in focus (i.e. the object passed to the expression) to the specified type. See Using adapt for more information. |
| and | AND the results from evaluating the sub-elements |
| count | Use to count the number of elements in a collection. The value attribute be an integer or a supported wildcard. See Using count for more information. |
| equals | Use to check equality of the focussed object with the specified value attribute |
| instanceof | Use to perform an instanceof check on the object in focus. See Using instanceof for more information. |
| iterate | Use to iterate over a collection, if the focussed object is of type java.util.Collection. See Using iterate for more information. |
| not | NOT the results from evaluating the sub-elements |
| or | OR the results from evaluating the sub-elements |
| reference | This is the element we use to refer to an expression defined under org.eclipse.core.expressions.definitions. The definitionId is the unique id of the expression definition to use for the evaluation. |
| systemTest | Use to test a system property, where property is the name of the property to get via System.getProperty, and value is the expected value to test against (as String value). |
| test | Use this element to test the value of a specific property on the focussed object. See Using test for more information. |
| with | Use to change the object to inspect or focus on to the object referenced by the variable attribute. See the list of available expression variables. |
| resolve | Resolve does almost the same as with, but it allows the use of a custom IVariableResolver, and passing the specified args as arguments to the variable resolver. More detail might be topic of a future blog post. I must admit, I have never used this one. |
Note on String values
The value attribute for the above elements gets specified as some string. Here follows the extract from the Eclipse online help on how that String value might get converted:
When specifying a value to be tested against any of these expressions, the value is assumed to be a string except for when the following conversions are successful:
the conversion into a Boolean, Float, or Integer can be suppressed by surrounding the string with single quotes.
Using adapt
Adapt is used to adapt the object in focus (you can see this as the object provided or specified by the parent element) to the type specified its the type attribute. Any sub-elements of the adapt element will be evaluated against the adapted object. Read up about IAdapterFactory and IAdaptable interfaces for more information about adaption.
If the object can be adapted, the adapt evaluate to true. E.g. we can define an expression for evaluating if something adapts to the ICountable interface.
|
Using instanceof
This is used to perform an instanceof check on the object in focus. We can for example enhance our Annotate eBook menu contribution in the File menu to only display if at least on of the selected items is an instance of java.lang.String (iterate gets discussed here):
|
Using iterate
Iterate can be used if the object in focus is a java.util.Collection (e.g. when with is used in the parent element and the variable attribute is set to “selection“). It iterates through the collection, and evaluate the sub-elements against each item in the collection.
The operator attribute can be set to and or or. For and, every item must cause the sub-elements of the expression to evaluate to true, and for or, at least one must evaluate to true.
The ifEmpty attribute can be set to true or false. If true, then the iterate expression will evaluate to true for empty collections, else to false.
See the example under the instanceof section.
Using count
The count element’s value attribute can take an integer value as parameter if the collection needs to contain the exact number of items. However, the following wildcards are also allowed:
| * | Any number of items |
| ? | Zero or one item |
| + | One ore more items |
| ! | No items |
See our first simple visibleWhen example for usage.
Using test
Test can be used to evaluate the state (i.e. value) of a specific property of the focussed object. The test expression can evaluate to true, false or not-loaded if the property tester (implemented by a Java class) is not loaded.
| property | specifies the name of the property of the object to test |
| args | specifies additional arguments to pass to the property tester |
| value | the value we expect the property to be |
| forcePluginActivation | if this is set to true, the plugin that contributes the property tester class will be loaded to enable the evaluation, if it is not loaded yet. However, this loading will only happen if the evaluation context used allows plugin activation. What does this mean: do not depend that when you set this flag to true, the plugin containing the property tester code will actually be loaded. |
In a future blog I will discuss how to implement your own property testers; quite a powerful feature. For now, let me just point you to some property testers available for your enjoyment. You can follow the links for the detailed code level information, or else have a look at the Propery Testers section in the Command Core Expressions wiki page for a summary.
Core Expression Variables
I was planning to list the most common variables available for core expressions here and discuss some of them, but time caught up with me. For now I will point you to:
Note: if you use the selection variable, you need to make sure the View that you are expecting a selection from is a SelectionProvider for the platform by registering it as a selection provider, e.g. by calling getSite().setSelectionProvider(viewer).
Coming soon…
References
Enough said.
Leave a Reply
You must be logged in to post a comment.