How to integrate a custom ISelectionProvider with Eclipse enabledWhen expressions? - eclipse-rcp

I have a custom graphical EditorPart in a Eclipse RCP application.
It sets a custom ISelectionProvider in the createPartControl(..) method:
#Override
public void createPartControl(Composite parent) {
// [snip]
getSite().setSelectionProvider((ISelectionProvider)model.getSelection());
}
I have two ViewParts listening to selection changes via the ISelectionService. They get notified when the selection in the EditorPart changes. So far so good.
Now I've added a handler using the following XML:
<handlerclass="my.custom.Handler" commandId="org.eclipse.ui.edit.delete">
<enabledWhen>
<count value="+"/>
</enabledWhen>
</handler>
If the selection in the EditPart contains > 0 elements, this should enable the handler my.custom.Handler, but it doesn't.
It is, however enabled if the selection provided by built-in selection providers changes to > 0 element (i.e. those provided by JFace viewers).
Any hint how to integrate a custom implementation of ISelectionProvider with the expression framework used in the handler declaration?

enabledWhen can contain any expression. You need to specify that you want the selection variable there. See here for an example: http://eclipse-tips.com/tutorials/1-actions-vs-commands?start=1

Related

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 hide action or actionset in Navigate menu

I am extending an extension point org.eclipse.ui.actionSets where I am creating element actionSet which contains action element inside. This asctionset is placed inside Navigate menu of eclipse For example:
<actionSet
label="%CNavigationActionSet.label"
description="%CNavigationActionSet.description"
visible="false"
id="xxx.ui.NavigationActionSet">
<action
class="xxx.opentype.OpenTypeAction"
definitionId="xxx.navigate.opentype"
helpContextId="xxxui.open_type_action"
icon="icons/xxx.gif"
id="xxx.ui.actions.OpenType"
label="Open Element"
menubarPath="navigate/open.ext2"
toolbarPath="org.eclipse.search.searchActionSet/Search"
tooltip="%OpenTypeAction.tooltip">
</action>
</actionSet>
Now I want to hide this action when certain conditions are met in Eclipse. Is there a way to hide (set visibility to false etc.) of this action in navigate menu?
Right now best what I figured out is to disable action when conditions are met, but this is not enough:
public class OpenTypeAction implements IWorkbenchWindowActionDelegate {
//... some code
#Override
public void selectionChanged(IAction action, ISelection selection) {
action.setEnabled(!areConditionsMet());
}
//... some code
}
/Edit: Solution for me would be also to hide whole actionSet instead of action, is that possible?
/Edit2: To clarify what my conditions are - my editor can contain files with multiple file extensions, I want to show this action only for files which end with certain file extension.

How to add action item to the coolbar of e4 eclipse rcp application?

I am currently trying to port my eclipse 3 rcp application to e4.The major hurdle I am facing is to use action item which i was using in e3.In eclipse 3 application i was creating action item of coolbar by extending action.The code was looking like below spinets.
public class Testaction extends Action {
private IWorkbenchWindow window;
public Testaction (IWorkbenchWindow window, String string) {
setText(string);
setToolTipText(string);
setId("ID");
setImageDescriptor(Activator.getImageDescriptor("/icons/some.png"));
this.window = window;
}
#override
public void run() {
/**
Do something
**/
super.run();
}
was adding it to coolbar through
toolbar.add(demoaction);
But with e4 this part seems to be changed and I understand that there we need to have annotation #Execute which will excute the contribution which we will be giving through setcontribuitionuri as below snippet
part.setContributionURI(
"bundleclass://bundle/bundle.contribuitionclass");
I just want to know whether I can use my old action class here or i need to port everything to newer style .
Any help on this will be appreciated.Thanks in advance...
e4 does not support Actions for model elements in the Application.e4xmi.
The simplest conversion is to use a Direct ToolItem in the tool bar. However using a Handled ToolItem with a Command and Handler is more flexible.
In either case the Image, Label and Tooltip are specified in the Application.e4xmi.

How to create custom image decorator in java file using eclipse plugin

I would like to use some decorators in my Eclipse plugin. I have created a plugin where I created my own editor for my own .test file. If the user edits .test file and saves it. The file must show some decorations not only the .test file but also the project must show the decorator. I am stuck with this problem I can't find any good tutorial to create decorators.
I Have seen some of the websites like https://www.eclipse.org/articles/Article-Decorators/decorators.html but I couldn't get the exact point.
Will some one please tell me how to create custom decorator for my eclipse plugin.
A ILightweightLabelDecorator is the most common type of decorator
Declare this in your plugin.xml with something like this:
<extension point="org.eclipse.ui.decorators">
<decorator
id="my.decorator.id"
class="my.decorator.Decorator"
label="My Decorator"
state="true"
lightweight="true"
adaptable="true">
<enablement>
<objectClass name="org.eclipse.core.resources.IResource"/>
</enablement>
</decorator>
</extension>
You will have to adjust the enablement to suit what you want.
Your decorator class would be something like:
public class Decorator extends BaseLabelDecorator implements ILightweightLabelDecorator
{
#Override
public void decorate(final Object element, final IDecoration decoration)
{
// TODO call decoration methods to add overlay images or prefix / suffix text
}
}

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>
...