mark file as active - eclipse plugin - eclipse

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));

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.

Select editor programmatically

I have written an Eclpse plugin that contains several editor types. For each editor a content type is associated. In some situations I have two possible editors for the same contenttype. I know that I can select the editor via "Open with". But I would like to decide automatically which editor should be opened.
Here is an example
In one plugins I have got the following extension point definitions:
<extension
point="org.eclipse.ui.editors">
<editor
class="de.dstg.adsplus.editors.program.MacroEditor"
contributorClass="de.dstg.adsplus.editors.core.ADSTextEditorActionContributor"
default="true"
icon="icons/macro.png"
id="de.dstg.adsplus.editors.editors.macroEditor"
name="ADS Macro Editor">
<contentTypeBinding
contentTypeId="de.dstg.adsplus.macro">
</contentTypeBinding>
</editor>
</extension
In another plugin I have this definiton:
<extension
point="org.eclipse.ui.editors">
<editor
class="de.dstg.adsplus.focusededitor.FocusedEditor"
contributorClass="de.dstg.adsplus.focusededitor.FocusedEditorContributor"
icon="icons/dveditor.png"
id="de.dstg.adsplus.focusededitor"
name="ADS Focused Editor">
<contentTypeBinding
contentTypeId="de.dstg.adsplus.macro">
</contentTypeBinding>
When I double click on a file with this content type I would like to decide programmatically which editor to open depending on the content of the file or the location where it is stored.
I have tried to find a method that I could implement but without success.
You could use two different content types both using the same file extensions and use a 'content type describer' to distinguish the files.
The content type describer is defined in the content type extension point:
<extension point="org.eclipse.core.contenttype.contentTypes">
<content-type id="ABC"
base-type="org.eclipse.core.runtime.xml"
file-extensions="a,b,c">
<describer class="org.eclipse.core.runtime.content.XMLRootElementContentDescriber2">
</describer>
</content-type>
The content describer class implements IContentDescriber or ITextContentDescriber. Eclipse calls the describe method to find out if the file is valid for the content type (and to get information about other attributes of the file).

Populate extension point's element attribute during runtime

Here is my use case. I have an Editor that different plugins can use to display their data. These plugins can create (with intervention from user - wizards) different files that Editor can accept: .p1, .p2, etc. Each plugin contributes file extensions of files that it produces and this data is available via custom extension point. I need a way, if possible to "inject" this data into org.eclipse.ui.editors extension point's extensions attribute.
One way I was thinking about doing this is in a plugin that is called early enough collect file extensions from all plugins that use my extension point and write these values into plugin.properties file's key like supportedFileExtension and extension point org.eclipse.ui.editors will in turn consume this file:
<extension
point="org.eclipse.ui.editors">
<editor
class="MyEditor"
contributorClass="MyActionBarContributor"
default="false"
extensions="%supportedFileExtensions"
id="my.com.editor"
name="My Editor">
</editor>
I also saw class ExtensionParameterValues which is something I can possibly use, but for developer who might want to reuse this little mechanism, it might not be obvious enough what's going, especially when extensions attribute would be empty when using ExtensionParameterValues class. Of course I can put this in documentation, but who reads that, right? :)
Perhaps I am overlooking something simple and there is an easier way to do what I am trying to accomplish?
Rather than using extensions directly you can Eclipse Content Types to do this. First define a base content type:
<extension
point="org.eclipse.core.contenttype.contentTypes">
<content-type
id="contenttype.base"
name="Base content type"/>
Then your different plugins can define a content type for their file extensions using a a content type derived from the base type:
<content-type
base-type="contenttype.base"
file-extensions="p1"
id="contenttype.p1"
name="P1 content type"/>
<content-type
base-type="contenttype.base"
file-extensions="p2"
id="contenttype.p2"
name="P2 content type"/>
For your editor don't specify any extensions, instead use the contentTypeBinding for the base type:
<extension
point="org.eclipse.ui.editors">
<editor
class="MyEditor"
contributorClass="MyActionBarContributor"
default="false"
id="my.com.editor"
name="My Editor">
<contentTypeBinding
contentTypeId="contenttype.base"/>
</editor>
The editor will now be used for all content types based on the base content type.

Adding context to my view and binding key to this context

My question is same as asked here. But the solution provided there not works for me.
I have activated the context as said in the answer by greg-449 in createPartControl of my view.
IContextService contextService = IContextService)getSite().getService(IContextService.class);
contextService.activateContext(myViewContextId);
When my view was activated I am getting below warning on eclipse console
!MESSAGE A conflict occurred for CTRL+F:
Binding(CTRL+F,
ParameterizedCommand(Command(myFindCmdId,Find,
,
Category(org.eclipse.core.commands.categories.autogenerated,Uncategorized,Commands that were either auto-generated or have no category,true),
org.eclipse.ui.internal.WorkbenchHandlerServiceHandler#f41266e,
,,true),null),
org.eclipse.ui.defaultAcceleratorConfiguration,
myViewContextId,,,system)
Binding(CTRL+F,
ParameterizedCommand(Command(org.eclipse.ui.edit.findReplace,Find and Replace,
Find and replace text,
Category(org.eclipse.ui.category.edit,Edit,null,true),
org.eclipse.ui.internal.WorkbenchHandlerServiceHandler#24ad92b0,
,,true),null),
org.eclipse.ui.defaultAcceleratorConfiguration,
org.eclipse.ui.contexts.window,,,system)
===Plugin.xml has ====
<extension
point="org.eclipse.ui.contexts">
<context
id=<myViewContextId>
name="abc">
</context>
</extension>
<extension
point="org.eclipse.ui.bindings">
<key
commandId=<myFindCmdId>
contextId=<myViewContextId>
schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
sequence="M1+F">
</key>
//some more key binding here
</extension>
To avoid the conflict message define you own key binding scheme using the org.eclipse.ui.bindings extension point and specify the standard org.eclipse.ui.defaultAcceleratorConfiguration as the parent id for the scheme. Put your key bindings in this new scheme.
Use:
org.eclipse.ui/KEY_CONFIGURATION_ID=schemeid
in your plugin_customization.ini to select your scheme as the default.
More here
Note: If your Ctrl+F is a Find command you should hook in to the existing Eclipse find/replace retargetable action rather than defining new commands and key bindings.
So for Find do not define any command, handler or key bindings. Instead in your ViewPart use
IActionBars bars = getViewSite().getActionBars();
bars.setGlobalActionHandler(ActionFactory.FIND.getId(), your find Action);
Try to add parentId="org.eclipse.ui.contexts.window" into your new context:
<extension
point="org.eclipse.ui.contexts">
<context
id=<myViewContextId>
name="abc">
parentId="org.eclipse.ui.contexts.window">
</context>
</extension>