How to enable a command only when the selected element has certain property? - eclipse

I'm building am eclipse plugin and I have a tree representation where I display the structure of an element of type A(see below).
Class A{
List<B> children;
}
Abstract Class B{
...
}
Class C extend B{
...
}
Class D extend B{
...
}
I have a command which can start only when the selected element in the three is an instance of A.
This is the expression I'm using.
<extension point="org.eclipse.core.expressions.definitions">
<definition id="SelectionOfA">
<with variable="selection">
<and>
<count value="1"></count>
<iterate ifEmpty="false" operator="or">
<instanceof value="A"></instanceof>
</iterate>
</and>
</with>
</definition>
</extension>
Now I would like to refine this condition. I would like to enable the command only when an instance of A is selected and the list children contains at least an element which is instance of C.
I tried by keeping this expression and defining a new one. Then I will enable the command only if both the expressions are true. I started from the expression reported above and I tried to replace the tag instanceof with the tags with, iterate and adapt without a good result.
How can I do it?

I would implement a property tester to check if the condition is met.
Something like this should do the work:
public class YourConditionTester extends PropertyTester {
public boolean test(final Object receiver, final String property, final Object[] args, final Object expectedValue) {
if (property.equals("isA_and_hasC")) {
return (true if your condition is met, otherwise false)
}
return false;
}
}
Then, instead of instanceof use test with property set (e.g.) to "isA_and_hasC".
Look here for more info about property testers.

Related

Xtext, get Iselection Input in the LaunchMydslShortcut

I'm trying to make a simple DSL with Xtext and execute it with an interpreter, the grammar is the initial Hello Word project.
I can can execute the .Text file successfully.
In the org.xtext.example.mydsl.ui project I write this in the plugin.xml file To run the Project from my class LaunchMydslShortcut.
<extension
point="org.eclipse.debug.ui.launchShortcuts">
<shortcut
class="org.xtext.example.mydsl.ui.MyDslExecutableExtensionFactory:org.xtext.example.mydsl.ui.launch.LaunchMydslShortcut"
icon="icon/sample.gif"
id="org.xtext.example.mydsl.u.launchMyDsl"
label="MyDsll"
modes="run">
<contextualLaunch>
<enablement>
<with variable="selection">
<count value="1"/>
<iterate
ifEmpty="false"
operator="and">
<adapt type="org.eclipse.core.resources.IFile"/>
<test property="org.eclipse.debug.ui.matchesPattern"
value="*.mydsl"/>
</iterate>
</with>
</enablement>
<contextLabel
mode="run"
label="Run Mydsl"/>
</contextualLaunch>
</shortcut>
</extension>
This is my LaunchMydslShortcut class :
class LaunchMydslShortcut implements ILaunchShortcut {
#Inject
private IResourceForEditorInputFactory resourceFactory;
override launch(ISelection selection, String mode) {
println("launch from selection")
}
override launch(IEditorPart editor, String mode) {
val input = editor.editorInput
if (editor instanceof XtextEditor && input instanceof FileEditorInput) {
val resource = resourceFactory.createResource(input)
resource.load(newHashMap())
println("launch Doooone")
}
}
}
However, I'm expecting to use launch(IEditorPart editor, String mode) function, but it executes the launch(ISelection selection, String mode).
so the question would be, what's the différence between the two? why my project is using the first? and how do I use the second?
The first one void launch(ISelection selection, String mode) is called when you launch your generator from the package explorer for example.
The second one void launch(IEditorPart editor, String mode) is called when launching from an editor context menu.
You can use a Utility to get the input file you need and then create an IResource.
Good example is in org.eclipse.xtext.xtext.launcher.WorkflowLaunchUtils.workflowFileFor(ISelection) and org.eclipse.xtext.xtext.launcher.WorkflowLaunchUtils.workflowFileFor(IEditorPart) it works with mwe2 files but it is easy to adopt it for your DSL.

How to assign a shortcut key to run a particular EASE script

I am curious whether it is possible to assign a shortcut key to run a particular EASE script. I know that I can add scripts to UI, but for me applying of shortcut keys is more familiar and convenient way to do my work.
Maybe, first I should create a popup-menu item and then assign a key to the item. So I've added the context menu item but I can not find any reference to the item in Preferences>>General>>Keys.
I find out the way to run a particular EASE script typing a sequence of keys:
create an eclipse plugin project;
add extension points to define a key binding, a command handler and an ease module;
write a module class and a command handler class.
The command handler's method called "execute" is invoked when I type the sequence of keys. As I can use the module to access the command handler synchronously, so I can assign code to be run from within the "execute" method.
This is plugin.xml:
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<plugin>
<extension point="org.eclipse.ui.bindings">
<key sequence="Ctrl+Shift+D"
commandId="m5.command_0"
schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
contextId="org.eclipse.jdt.ui.javaEditorScope"/>
</extension>
<extension point="org.eclipse.ui.commands">
<command name="Execute custom command"
defaultHandler="m5.handlers.CustomHandler_0"
description="Execute custom command"
categoryId="org.eclipse.jdt.ui.category.source"
id="m5.command_0">
</command>
</extension>
<extension
point="org.eclipse.ease.modules">
<module
category="org.eclipse.ease.category.system"
class="m5.handlers.Module1"
id="M5.module1"
name="M5.module1"
visible="true">
</module>
</extension>
</plugin>
This is the command handler:
package m5.handlers;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
public class CustomHandler_0 extends AbstractHandler {
private static Runnable runnable;
protected synchronized static void setRunnableToExecute(Runnable codeToRun){
runnable = codeToRun;
}
#Override
public Object execute(ExecutionEvent arg0) throws ExecutionException {
System.out.println("command_0");
if(runnable != null){
runnable.run();
}
return null;
}
}
This is the module:
package m5.handlers;
import org.eclipse.ease.modules.AbstractScriptModule;
import org.eclipse.ease.modules.WrapToScript;
import m5.handlers.CustomHandler_0;
public class Module1 extends AbstractScriptModule{
#WrapToScript
public void setCommand_0(String code){
CustomHandler_0.setRunnableToExecute(new Runnable(){
#Override
public void run() {
getScriptEngine().executeAsync(code);
}
});
}
}

Switching GWT.create(XXX.class) by Custom Annotation

I hope that you're all coding well. So... I was refactoring the client side of the GWT app I work on and I was wondering about something. Looking after an answer days after days, I decided to ask you for your point of view...
The title is quite understanding, but, there is a snippet of what I'd like to do.
I'd like to change stuff like this
public AnnotatedObject annotated = GWT.create(AnnotatedObject.class);
by something like this
#CreativeAnnotation
public AnnotatedObject;
I had to say that in my xxx.gwt.xml, I have done something like this :
<replace-with class="package.AnnotationObject2">
<when-type-is class="package.AnnotationObject" />
</replace-with>
As you can see, my deffered replacement class is AnnotationObject2, and for the moment, I add a line between the ones above and I have :
<replace-with class="package.AnnotationObject1">
<when-type-is class="package.AnnotationObject" />
<when-property-is name="type" value="object1" />
</replace-with>
<replace-with class="package.AnnotationObject2">
<when-type-is class="package.AnnotationObject" />
<when-property-is name="type" value="object2" />
</replace-with>
I don't really like to play with metadata of my xxx.html, so the result I'd like is this one :
#CreativeAnnotation(type = "object2")
public AnnotatedObject;
So, do you think that sort of thing is possible with GWT (I have to say that I work with GWT 2.5, 'cause of my client desires) ? If yes, may you help me ?
Thanks in advance.
EDIT : I mean, I know about GIN... Just wondering how to do it from scratch.
You can achieve this by using dependency injection with GIN.
GIN automatically use GWT.create() to create an object that has to be injected.
Ex:
class MyView {
interface MyUiBinder extends UiBinder<Widget, MyView> {
}
#Inject
MyView(MyUiBinder uiBinder) {
initWidget(uiBinder.createAndBindUi(this));
}
}
And with dependency injection, you also specify which implementation of your interface to instantiate in your GIN module:
public class MyModule extends AbstractGinModule {
protected void configure() {
bind(AnnotationObject.class).annotatedWith(Names.named("object1").to(AnnotationObject1.class);
bind(AnnotationObject.class).annotatedWith(Names.named("object2").to(AnnotationObject2.class);
}
}
And then in your code:
public class MyClass {
#Inject
public MyClass(#Named("object1") AnnotationObject annotationObject) {
...
}
}
You can also use custom binding annotation instead of the Named annotation.
You can write your own generator if you don't want to use GIN - for something like this it would be pretty trivial.

XStream different alias for same class (Map.class) for different fields

I am using XStream to convert a Java class which has fields of the type java.util.Map. I have a converter for java.util.Map which displays the key of the Map as an xml element and the value of the map as the value for the xml element. I have registered the converter using registerConverter method. When I perform the marshalling, I get the following output.
<cart account_id="123" shift_id="456" account_postings_id="641">
<supervisor_id>555</supervisor_id>
<payments>
<map sequence="1">
<amount>123.45</amount>
<billing_method>12345</billing_method>
<form>card</form>
<delivery_mode>Q</delivery_mode>
</map>
<map sequence="2">
<amount>123.45</amount>
<person_id>2333</person_id>
<form>cash</form>
<delivery_mode>Q</delivery_mode>
</map>
</payments>
<items>
<map sequence="3">
<amount>1.00</amount>
<type>pay_toll</type>
<toll_id>1234</toll_id>
</map>
</items>
</cart>
Instead of the map tags appearing, I would want to use different tags based on the field name in the class. For example, the Payments list will have tag name payment and the Items list will have a tag name item for each Map element.
How do we dynamically set alias based on field in the same class?
-Anand
I used XStream to create atom feed reports. Entries in the contents can be of different object classes and I wanted to use the class name dynamically. Here is my solution. I created a ObjectContentConverter and passed the XStream on, and then use xstream.aliasField() with getClass().getSimpleName().
private class ObjectContentConverter implements Converter {
XStream xStream;
private ObjectContentConverter(XStream xStream) {
this.xStream = xStream;
}
#Override
public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
String className = WordUtils.uncapitalize(source.getClass().getSimpleName());
xStream.aliasField(className, Content.class, "objectContent");
xStream.marshal(source, writer);
}
#Override
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
#Override
public boolean canConvert(Class type) {
return true; //To change body of implemented methods use File | Settings | File Templates.
}
}
xStream.registerLocalConverter(Content.class, "objectContent", new ObjectContentConverter(xStream));

Confused about IAdaptable with IActionFilters

I'm confuse about IAdaptable and related classes. Which class is the adapter, the adaptee, the adaptable type?
[Context]
I have a context menu for entries of a table/tree viewer. Certain actions in the context menu must not be visible depending on the state of the respective object in the viewer (i.e. attribute value of a row in the table viewer).
I can achieve this with a config like this in plugin.xml:
<extension
point="org.eclipse.ui.popupMenus">
<objectContribution
adaptable="false"
id="<some_id>"
objectClass="<object_class_of_viewer_entry>">
<visibility>
<objectState name="buildable" value="true"/>
</visibility>
<action
class="<my_action_class>"
However, this only works if the object class implements org.eclipse.ui.IActionFilter.
[Problem]
My object class can't implement IActionFilter, I don't want to change its interface. Hence, I need to work around that using the IAdaptable mechanism.
Reading the Eclipse documentation left me all puzzled with terms (adapter, the adaptee, adaptable type) and I'm still confused about how to go about my problem.
The object class (referred to by in the above config) must remain untouched.
My approach was the following.
<extension
point="org.eclipse.core.runtime.adapters">
<factory
adaptableType="<object_class_of_viewer_entry>"
class="MyFactory">
<adapter
type="org.eclipse.ui.IActionFilter">
</adapter>
</factory>
</extension>
MyFactory is like this:
public class MyFactory implements IAdapterFactory {
private static final Class[] types = {
<object_class_of_viewer_entry>.class,
};
#Override
public Object getAdapter(Object adaptableObject, Class adapterType) {
return new <class_that_implements_IActionFilter>((<object_class_of_viewer_entry>) adaptableObject);
}
#Override
public Class[] getAdapterList() {
return types;
}
}
What's wrong about this? Where did I miss something?
Turns out everything, well, almost everything, was correct. I had simply mixed up interface and implementation of object_class_of_viewer_entry in the plugin.xml.
Two articles that helped: http://www.eclipsezone.com/articles/what-is-iadaptable/ and http://wiki.eclipse.org/FAQ_How_do_I_use_IAdaptable_and_IAdapterFactory%3F