I came around the requirement to enable the default cut, copy and paste function as menu entries within the main menubar. When adding the commands org.eclipse.ui.edit.cut, org.eclipse.ui.edit.copy and org.eclipse.ui.edit.paste to my menubar using the org.eclipse.ui.menus extension point. Unfortunately, these menu entries where disabled all the time. This was pretty comprehensible, as there was no active handler available. So I did register an appropriate handler (working like the Eclipse WidgetMethodHandler) using the IHandlerService. It takes the currently focussed element and checks whether this Control has the necessary cut(), copy() or paste() method to invoke and calls the required method on execution. So far, so good, my menu entries were now enabled - at least sometimes?!? The reason for that was the isHandled() method of my handler which returns true only if the method is available on the currently focussed element.
/** {@inheritDoc} */
@Override
public boolean isHandled() {
return isTargetMethodAvailable(Display.getCurrent().getFocusControl()) != null;
}
As the isHandled() is called only on the context part’s (IWorkbenchPart) activation, the state of the handler is only requested once for the default focus Control of the part. So the state of the commands stays the same for the whole part activation. Additionally, a ‘no active handler available’ exception is thrown, if the menu entry is selected with a focussed Control not supporting the method. Bad luck.
So, what to do now? I ended up registering a focus Listener for all elements of the part to keep the command state in sync with the handler state.
// create a listener for tracking the focus
final Listener listener = new Listener() {
/** {@inheritDoc} */
@Override
public void handleEvent(Event event) {
ICommandService commandService = (ICommandService)workbenchPart.getSite().getService(ICommandService.class);
commandService.refreshElements(commandId, null);
}
};
The refreshElements() method calls the updateElement() method of active handlers for the given command ID implementing the IElementUpdater interface. So I let my handler implement that interface, the interface method simply fired an HandlerEvent stating that the enabled state changed.
/** {@inheritDoc} */
@Override
public void updateElement(UIElement element, Map parameters) {
fireHandlerChanged(new HandlerEvent(this, true, false));
}
The only thing left to do was to implement the isEnabled() method which is used to determine the commands enablement state.
/** {@inheritDoc} */
@Override
public boolean isEnabled() {
return isTargetMethodAvailable(Display.getCurrent().getFocusControl()) != null;
}
There you are, it works!