- A command (which only declares the abstract concept of the semantic behavior):
<extension point="org.eclipse.ui.commands">
<command
description="Do something with a model element"
id="my.command.id"
name="Do Something">
</command>
</extension>
ActionDelegate):<extension point="org.eclipse.ui.handlers">
<handler
class="my.contribution.MyCommandHandler"
commandId="my.command.id">
</handler>
</extension>
<extension point="org.eclipse.ui.menus">
<menuContribution locationURI="popup:org.eclipse.ui.popup.any?after=additions">
<command
commandId="my.command.id"
style="push">
<visibleWhen>
<with variable="activeMenuSelection">
<iterate>
<instanceof
value="my.model.MyObject">
</instanceof>
</iterate>
</with>
</visibleWhen>
</command>
</menuContribution>
</extension>
Note that the locationURI offers a lot of options - the case above simulates the objectContribution behavior, as the command is added to any popup menu and the visibility is determined by the selected objects' types. Instead of behaving like an objectContribution, we can simply change the locationURI to menu:<view-or-menu-id> or to toolbar:<view-or-toolbar-id> in order to contribute the command to a view's menu or toolbar, respectively. Naturally, in these cases, we don't need the visibleWhen constraint. The command handler implemtation is a lot simpler than the action delegate handler, as the abstract class org.eclipse.core.commands.AbstractHandler does all the extra work (listener implementation etc.) for us. The only method, we have to implement ourselves is execute():
package my.contribution;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.ui.handlers.HandlerUtil;
public class MyCommandHandler extends AbstractHandler {
@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
IStructuredSelection selection = (IStructuredSelection) HandlerUtil.getCurrentSelectionChecked(event);
MyObject object = (MyObject) selection.getFirstElement();
// do something with MyObject
}
}
Again, until here, we only implemented a command which is enabled always. Now, if we want to enable the command only, if the selected model element fulfills a certain constraint, in the old API we needed an adapter. In the new API, the adapter is made implicit using the concept of a PropertyTester. A PropertyTester can be used to add custom testable properties to arbitrary classes. For our example, the declaration and looks like this:
<extension point="org.eclipse.core.expressions.propertyTesters">
<propertyTester
class="my.package.MyObjectPropertyTester"
id="my.proptester.id"
namespace="my.property.namespace"
properties="type"
type="my.model.MyObject">
</propertyTester>
</extension>
and the implementation is as follows:
package de.feuh.st.requipse.project;
import org.eclipse.core.expressions.PropertyTester;
public class ArtifactPropertyTester extends PropertyTester {
@Override
public boolean test(Object receiver, String property, Object[] args,
Object expectedValue) {
MyObject obj = (MyObject)receiver;
if(property.equals("type")) {
return expectedValue.equals(obj.getType());
}
else {
return false;
}
}
}
This way, we have defined a property called type in the namespace my.property.namespace which applies to objects which are instance of my.model.MyObject. The implementation then compares the value of the object's getType() method to a given expected value and returns the result. As a final step, we have to use the PropertyTester in our handler declaration. We enhance the handler as follows:
<extension point="org.eclipse.ui.handlers">
<handler
class="my.contribution.MyCommandHandler"
commandId="my.command.id">
<enabledWhen>
<with variable="selection">
<iterate
ifEmpty="false"
operator="and">
<test
property="my.property.namespace.type"
value="FOO">
</test>
</iterate>
</with>
</enabledWhen>
</handler>
</extension>
This enables the command only if all of the selected objects return "FOO" for getType().
Further Reading:
