Introduction
This is a follow up to
Commands Part 6: Toggle & Radio menu contributions of fellow blogger
Prakash G.R.. He described how to use command toggle and radio states. Here I will show you how to drive other contributions in the Eclipse Workbench using a toggle command.
What we want to achieve
I needed to show another toolbar button when a certain toggle command was executed. Imagine something like "Show clock" that will show or hide a little clock in the worbench window status bar.
Such contribution can be easily added using a
menuContribution for the trim area. First create a toolbar in the trim area and then contribute controls/commands to this toolbar also using the
menuContribution extension point.
Since we want the clock contribution
<menucontribution locationuri="toolbar:mytoolbar">
<control class="test.ui.clocl.internal.ClockControlContribution" id="test.ui.clock">
<visiblewhen checkenabled="false">
<with variable="activeWorkbenchWindow">
<test args="test.ui.clock.ToggleCommand"
forcepluginactivation="true"
property="org.eclipse.core.commands.toggle"
value="true"/>
</with>
</visiblewhen>
</control>
</menucontribution>
That will create a toolbar contribution that is only visible when the
test.ui.clock.ToggleCommand is in the "
true" state, when its checked.
Lets define the command:
<command defaulthandler="org.eclipse.core.commands.extender.ToggleCommandHandler" id="test.ui.clock.ToggleCommand" name="Show clock">
<state
class="org.eclipse.ui.handlers.RegistryToggleState:true"
id="org.eclipse.ui.commands.toggleState">
</state>
</command>
How this command works and what the state is you have already read in Prakash's blog entry. The default handler for this command does a little more than the one in the latter mentioned blog entry. It is defined like this:
/**
* Generic command that toggles the executed command and re-evaluates property testers for the
* org.eclipse.core.commands.toggle
property.
*
*/
public class ToggleCommandHandler extends AbstractHandler {
public Object execute(final ExecutionEvent event) throws ExecutionException {
HandlerUtil.toggleCommandState(event.getCommand());
final IWorkbenchWindow ww = HandlerUtil.getActiveWorkbenchWindowChecked(event);
final IEvaluationService service = (IEvaluationService) ww.getService(IEvaluationService.class);
if (service != null) {
service.requestEvaluation("org.eclipse.core.commands.toggle");
}
return null;
}
}
How to toggle the visibility of the clock contribution
The connection between toggling the command and making the clock contribution visible is hidden in a property tester, that the clock contribution uses:
public class CommandsPropertyTester extends PropertyTester {
public static final String NAMESPACE = "org.eclipse.core.commands"; //$NON-NLS-1$
public static final String PROPERTY_BASE = NAMESPACE + '.';
public static final String TOGGLE_PROPERTY_NAME = "toggle"; //$NON-NLS-1$
public static final String TOGGLE_PROPERTY = PROPERTY_BASE + TOGGLE_PROPERTY_NAME;
public boolean test(final Object receiver, final String property, final Object[] args, final Object expectedValue) {
if (receiver instanceof IServiceLocator && args.length == 1 && args[0] instanceof String) {
final IServiceLocator locator = (IServiceLocator) receiver;
if (TOGGLE_PROPERTY_NAME.equals(property)) {
final String commandId = args[0].toString();
final ICommandService commandService = (ICommandService)locator.getService(ICommandService.class);
final Command command = commandService.getCommand(commandId);
final State state = command.getState(RegistryToggleState.STATE_ID);
if (state != null) {
return state.getValue().equals(expectedValue);
}
}
}
return false;
}
}
It is defined in plugin.xml like this:
<propertytester
class="org.eclipse.core.commands.extender.internal.CommandsPropertyTester"
id="org.eclipse.core.expressions.testers.CommandsPropertyTester"
namespace="org.eclipse.core.commands"
properties="toggle"
type="org.eclipse.ui.services.IServiceLocator"/>
That means we define a new property for the namespace "
org.eclipse.core.command" and the property is named "toggle". It will operate on
IServiceLocator variables. Such variable that is an
IServiceLocator is the "
activeWorkbenchWindow" variable. Now you should understand the
visibleWhen expression of the clock contribution. It should be only visible when the toggle for the clock toggle command is "true". The re-evaluation of the property testers is triggered by the generic
ToggleCommand.
A little tip at the end
If you put the
ToggleCommand and property tester in a seperate bundle for easier re-use in all your projects and other bundles make sure you either start the bundle at the beginning or set the "test" expressions "
forcePluginActivation" to true to let the Eclipse expression framework activate the bundle for you. Otherwise the property tester is completly ignored and the clock would be always visible.
Bonus
Since the state of the toggle is preserved in an instance preference value, the visibility of all associated contributions that use the property tester to check for the toggle state of the command is as well.
Of course you can also reverse the test expression for your contributions if you have a toggle command that says something like "Hide clock".
No comments:
Post a Comment