change the command ids default handler - eclipse-rcp

I need to change the command id's default handler . For example RestartWorkbenchHandler's command id is org.eclipse.ui.file.restart. So when we give the command is org.eclipse.ui.file.restart it will call the RestartWorkbenchHandler.
Now I wanted to restrict not to call the RestartWorkbenchHandler instead it should call my own Handlers when I give the org.eclipse.ui.file.restart. How do I do that?
Thanks
Bhanu

That handler is provided as the default handler (priority==0) for that command. AFAIK, though, the ID is org.eclipse.ui.file.restartWorkbench.
You can override it by providing another handler with a higher priority. You can use org.eclipse.ui.handlers:
<handler class="org.example.YourResetHandler"
commandId="org.eclipse.ui.file.restartWorkbench">
<activeWhen>
<with variable="activeWorkbenchWindow">
<instanceof value="org.eclipse.ui.IWorkbenchWindow"/>
</with>
</activeWhen>
</handler>
Or you can simply register another handler in your ActionBarAdvisor while making legacy actions:
IHandlerService srv = (IHandlerService) window.getService(IHandlerService.class);
srv.activateHandler(IWorkbenchCommandConstants.FILE_RESTART, new YourRestartHandler());

Related

Eclipse RCP dynamic MenuContribution hide and unhide with CoreExpression

I'm trying currently to add a visibleWhen condition for a MenuContribution in my Eclipse RCP application. We've different versions of our app and we've differentiate them with a IClientConfiguration interface/service which works more or less as feature toggles.
Depending on witch app-$version.product is called different implementations of the configuration will part of the app.
However.. get to the current situation: We've a menu which is defined in a common fragment.e4xmi and I would like to hide one menu depending on the configuration. For that I've added the toggle isAdminMenuActive(). I've hoped that I can create a CoreExpression and using (somehow) the return value of this service. But unfortunately I can't get this to work by now.
What I tried was the following:
fragment.e4xmi:
<elements xsi:type="menu:MenuContribution" xmi:id="_ZuL6oA4IEeqbk5lJVdc6WQ" elementId="com.example.client.menucontribution.administration" parentId="com.example.product.main.menu">
<children xsi:type="menu:Menu" xmi:id="_ngOY4LOMEemRpJf6BiOdqQ" elementId="com.example.client.menu.administration" label="%UI.general.administration">
<visibleWhen xsi:type="ui:CoreExpression" xmi:id="_rrmcQA4lEeqbk5lJVdc6WQ" coreExpressionId="com.example.client.configuration.adminMenuActiveExpression"/>
<children xsi:type="menu:HandledMenuItem" xmi:id="_B4RqsLONEemRpJf6BiOdqQ" elementId="com.example.client.menuitem.action.administration" label="%UI.action" tooltip="%UI.action" command="_XnSp8LOPEemRpJf6BiOdqQ"/>
</children>
</elements>
plugin.xml
<extension
point="org.eclipse.core.expressions.definitions">
<definition
id="com.example.client.configuration.adminMenuActiveExpression">
<with variable="com.example.client.configuration.adminMenuActive">
<equals
value="true">
</equals>
</with>
</definition>
</extension>
Startapp.java
#PostConstruct
public void init(IEclipseContext context) {
context.set(com.example.client.configuration.adminMenuActive,
configuration.isAdminMenuActive().toString());
}
The current behaviour is that the menu is never shown no matter which configuration is loaded. I've tried if the variable is added to the IEclipseContext and this happens very early in the start up phase of the application. Currently I've no idea what's wrong.
Rather than using a core expression in the fragment.e4xmi you can use an 'Imperative Expression'. You do this by changing the 'Visible-When Expression' in the fragment editor.
An imperative expression specifies a Java class which is called directly making it easier to access your code. The method tagged with #Evaluate is called to evaluate the expression. Maybe something like:
#Evaluate
public boolean evaluate(#Named("com.example.client.configuration.adminMenuActive") String active)
{
return Boolean.valueOf(active);
}
Using this makes it much easier to see what is happening.

How to make Eclipse enabledWhen expression work for selection in non-focused view?

I have a handler which is connected to a menu contribution and a command. The menu contribution adds a button to a view and I want to have the button enabled depending on a selection in the Debug view.
So here's the expression:
<handler
class="com.example.myhandler"
commandId=" com.example.mycommand">
<enabledWhen>
<with
variable="selection">
<iterate
ifEmpty="false">
<instanceof
value="org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext">
</instanceof>
</iterate>
</with>
</enabledWhen>
</handler>
This works absolutely fine to the point where the Debug view has focus, meaning that if I select the element in the Debug view, the added button in a separate view is also enabled (as desired). As soon as I click on the view where I added the button via the menu contribution, then it's suddenly disabled (I guess because the selection is empty even though it's still selected; but the Debug view has no focus). How can I make this work so that the selection is still considered independently of the Debug view's focus state?
(You appear to be asking a DSF specific question, which has a different answer to the "general" case your title refers to. As such this answer probably solves your problem, but may not solve the general case.)
A complete example of extending DSF-GDB is provided in the CDT source repo in the org.eclipse.cdt.examples.dsf.gdb bundle.
That example defines a new command org.eclipse.cdt.examples.dsf.gdb.command.showVersion:
<!-- Example showing how to add a custom command with toolbar/menu contributions with DSF.
The example command id is org.eclipse.cdt.examples.dsf.gdb.command.showVersion.
In this example, when run it will display the version of GDB that is connected. -->
<extension point="org.eclipse.ui.commands">
<command
categoryId="org.eclipse.cdt.debug.ui.category.debugViewLayout"
description="Show the GDB Version in a pop-up"
id="org.eclipse.cdt.examples.dsf.gdb.command.showVersion"
name="Show GDB Version">
</command>
</extension>
It goes on to show how to contribute the command to the menus with the org.eclipse.ui.menus extension point. Then binds the command to a command handler with the org.eclipse.ui.handlers extension point.
Up until this point, DSF behaves the same as "normal" commands. But in DSF (using the retargettable command infrastructure provided by platform debug), the handler is not directly the command you are trying to run, but is a subclass of DebugCommandHandler.
DSF then can bind that command, using adapters to the concrete command implementation, depending on what the selected debug session in the Debug view is. In the show version case, this is GdbShowVersionHandler (implementation of IDebugCommandHandler). The handler has a canExecute which can connect to the back end if needed (gdb) to see if the current selection is applicable. The canExecute receives something that can be converted into a DSF context object like this:
private Optional<ICommandControlDMContext> getContext(final IDebugCommandRequest request) {
if (request.getElements().length != 1 || !(request.getElements()[0] instanceof IDMVMContext)) {
return Optional.empty();
}
final IDMVMContext context = (IDMVMContext) request.getElements()[0];
ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(context.getDMContext(),
ICommandControlDMContext.class);
if (controlDmc != null)
return Optional.of(controlDmc);
return Optional.empty();
}
PS I added this example to CDT to help another extender a while back. The conversation on cdt-dev may be useful too? This was all added initially for this bug, with its associated gerrit which pulls all the changes for adding a new command into one place.

Eclipse plugin: overriding standard command handler

I'm trying to override an existing command handler in Eclipse. Specifically, I want to override the Run command (org.eclipse.debug.ui.commands.RunLast) so that it first terminates the process from the previous launch before starts the new one. I read this article, wrote a handler and associated it with the Run command:
<extension point="org.eclipse.ui.handlers">
<handler commandId="org.eclipse.debug.ui.commands.RunLast"
class="net.anggo.tnr.TnRHandler">
<activeWhen>
<with variable="activeContexts">
<iterate operator="or">
<equals value="net.anggo.tnr.TnREnabled"></equals>
</iterate>
</with>
</activeWhen>
</handler>
</extension>
I added activeWhen clause so that the new handler has a higher priority than the default handler. I activated TnREnabled context in an IStartup. But still, the default handler is run when I hit the Run menu item. I assume this is because the priority of the default handler is still higher than that of the new one. So my question is..
How can I calculate the priority of the default handler so that I can compare it with that of the new handler? Does my assumption seem correct that it is a priority issue? Is there a diagnostic way I can see what the problem is e.g. plugin spy? I'd appreciate any of help.

mark file as active - eclipse plugin

i wrote a plugin for a eclipse that let user creating my own type of project , the template of the project have some configuration files and I want to give the user the option to chose which one will be active, it's mean which one i will use when i will compile the project, i add an action of this files that let the user set it as active, my question is if there is any way to mark it in the package explorer(maybe bold ar with some border) as active so when user look at this he can know which one is the active now
Thanks
You can use the decorator extension point org.eclipse.ui.decorators. Add this to your plugin.xml:
<extension
point="org.eclipse.ui.decorators">
<decorator
adaptable="true"
class="MyDecoratorClass"
id="some.id.for.decorator"
label="Active Build Configuration Decorator"
lightweight="true"
location="BOTTOM_RIGHT"
state="false">
<enablement>
<and>
<objectClass
name="org.eclipse.core.resources.IResource">
</objectClass>
<or>
<objectClass
name="org.eclipse.core.resources.IProject">
</objectClass>
<objectClass
name="org.eclipse.core.resources.IFile">
</objectClass>
</or>
</and>
</enablement>
</decorator>
</extension>
Provide implementation in your MyDecoratorClass (or whatever name you choose) to check your project's active config and either adding text, or images. Perhaps have something like this: []
Whenever a user makes a modification that requires you to update the decorators so that the latest changes can be decorated you can use this:
// the resource whose properties changed and needs to be re-decorated
IResource resource = ...;
IDecoratorManager manager = PlatformUI.getWorkbench().getDecoratorManager();
IBaseLabelProvider decorator = manager.getBaseLabelProvider("id.of.my.decorator");
if (decorator != null)
((ILabelProviderListener) manager).labelProviderChanged(new LabelProviderChangedEvent(decorator, resource));

Eclipse RCP: how to observe the states of the cut/copy/paste commands?

I'm currently struggling with the following Eclipse RCP commands:
org.eclipse.ui.edit.cut
org.eclipse.ui.edit.copy
org.eclipse.ui.edit.paste
I'm using them as command contributions in the toolbar, but the UIElements (toolbar items) are not updated when the 'handled' state of those commands changes.
For testing I used a polling mechanism to verify that the state of those commands really changes depending on the currently focussed element, and I found out that the handler remains the same but the handler's 'handled' state changes properly, causing the commands 'handled' state to also change properly.
The only problem is, that neither one of those state changes causes a notification (neither on the command's ICommandListener, nor on the handler's IHandlerListener), so the UIElements won't get updated.
Here's some testing code to observe the states of a Command:
ICommandService commandService = (ICommandService) PlatformUI.getWorkbench().getService(ICommandService.class);
final String commandId="org.eclipse.ui.edit.copy";
Command command = commandService.getCommand(commandId);
command.addCommandListener(new ICommandListener() {
public void commandChanged (CommandEvent commandEvent) {
System.out.println(">> Command changed: " + commandId);
}
});
Am I missing something, or is this an bug in the cut/copy/paste handler implementations?
Any insights?
EDIT:
The commands are enabled all the time, and the handler is never exchanged, only the handler's 'handled' state (and thus also the commmand's 'handled' state) changes depending on which ui element has the focus. There is however no notification when this state changes.
This results in the toolbar buttons always being enabled, and pressing them will cause a org.eclipse.core.commands.NotHandledException: There is no handler to execute for command.
The handler which is registered for the cut/copy/paste commands is org.eclipse.ui.internal.handlers.WidgetMethodHandler. This handler checks if a given method is declared on the current display's focus control. When executed, that handler will invoke the method using reflection.
Snippet from WidgetMethodHandler:
public final boolean isHandled() {
return getMethodToExecute() != null;
}
The getMethodToExecute() will locate the current focus control using Display.getCurrent().getFocusControl(), and then check if the given trigger method is declared on it.
Widgets such as org.eclipse.swt.widgets.Text have cut(), copy() and paste() methods, so when the focus is on such a widget, the handler will return 'true' for isHandled().
This handler is however not aware when the current focus control changes (I think there isn't even a way to observe this on the Display), and thus can't notify about changes on its dynamic 'isHandled' state.
This results in the cut/copy/paste commands being fine for popup menus, but they're quite problematic when used in toolbars, as their UI elements can't be updated properly when the handler does no notifications.
This leaves me with either not using those commands in the toolbar, or having a polling mechansim to update the ui elements (which is also bad and error prone). :-(
Your problem is that you need to register a handler for anything that is not a text because Eclipse needs to know how to copy the currently selected "something" to the clipboard. That's what a handler does. This article in the Eclipse wiki will get you started how to create and register a handler.
I could be wrong, but the source of the problem is that the handler is always enabled.
See Platform Plug-in Developer Guide > Programmer's Guide > Plugging into the workbench > Basic workbench extension points using commands > Handlers.
The <activeWhen/> expressions in the
plugin.xml and programmatic core
expressions are used to help determine
the scope of a handlers activation.
For example, a specific window, a
specific Shell, an active part type or
active part.
<extension
point="org.eclipse.ui.handlers">
...
<handler
class="org.eclipse.ui.examples.contributions.view.SwapInfoHandler"
commandId="org.eclipse.ui.examples.contributions.view.swap">
<activeWhen>
<reference
definitionId="org.eclipse.ui.examples.contributions.view.inView">
</reference>
</activeWhen>
<enabledWhen>
<count
value="2">
</count>
</enabledWhen>
</handler>
...