Pregunta

I am in charge of refactoring the popup menus in my company's Eclipse Plugin to use the new commands/handler/menu extension point scheme. We had some business logic for when certain menu items should enabled or not, and this was handled through the onSelectionChanged method of the SelectionListener they applied to the action. I am now trying to control the enablement using a custom PropertyTester, but it seems that my custom PropertyTesters are not being loaded. I've followed Eclipse's doc as well as any tutorials I could find online and for some reason it just does not want to work. Even if I simply set the "test" method to return true, it doesn't work because the tester is never even loaded (I threw some break points in and they never get hit). I've tried setting the "forcePluginActivation='true'" flag in the test in the xml, but that also does not remedy the situation. Here is some code, with the company name replaced by "company" and the product replaced by "product"...

COMMAND XML

  <extension
         point="org.eclipse.ui.commands">
      <command
            categoryId="com.company.product.android.core.category2"
            id="com.company.product.android.core.commands.convertToProduct"
            name="Convert to product Android Project"
            description="The resources, jars and native library to begin developing an product for Android project application will be added to the Android project">
      </command>
      <category
            id="com.company.product.android.core.category2"
            name="Product Tools">
      </category>
   </extension>

HANDLER XML

   <extension
         point="org.eclipse.ui.handlers">
      <handler
            class="com.company.product.android.core.commands.ConvertToProduct"
            commandId="com.company.product.android.core.commands.convertToProduct">
        <enabledWhen>
            <reference
                definitionId="com.company.product.android.core.expressions.productProject">
            </reference>
        </enabledWhen>
      </handler>
   </extension>

DEFINITIONS XML

  <extension>
        point="org.eclipse.core.expressions.definitions">
    <definition
        id="com.company.product.android.core.expressions.androidProjectNature">
        <with variable="selection">
            <iterate ifEmpty="false">
                <test
                    property="org.eclipse.core.resources.projectNature"
                    value="com.android.ide.eclipse.adt.AndroidNature">
                </test>
            </iterate>
        </with>
    </definition>
    <definition
        id="com.company.product.android.core.expressions.productProject">
        <with variable="selection">
            <iterate ifEmpty="false">
                <test
                    property="com.company.product.android.expressions.productProjectProperty"
                    forcePluginActivation="true">
                </test>
            </iterate>
        </with>
    </definition>
  </extension>

MENU XML

   <extension
         point="org.eclipse.ui.menus">
      <menuContribution
         locationURI="popup:org.eclipse.ui.navigator.ProjectExplorer#PopupMenu?after=additions">
        <menu
               icon="icons/wht_ws.gif"
               id="com.company.product.android.core.tools"
               label="Product Tools">
            <visibleWhen>
                <reference 
                    definitionId="com.company.product.android.core.expressions.androidProjectNature">
                </reference>
            </visibleWhen>              
            <command
                commandId="com.company.product.android.core.commands.convertToProduct"
                label="Convert to Product Android Project"
                tooltip="The resources, jars and native library to begin developing an product for Android project application will be added to the Android project.">
            </command>
         </menu>
      </menuContribution>
   </extension>

PROPERTY TESTER XML

  <extension
    point="org.eclipse.core.expressions.propertyTesters">
    <propertyTester
        class="com.company.product.android.core.expressions.ProductProjectTester"
        id="com.company.product.android.core.expressions.productProjectTester"
        namespace="com.company.product.android.core.expressions"
        properties="productProjectProperty"
        type="java.lang.Object">
    </propertyTester>
  </extension>

PROPERTY TESTER JAVA

package com.company.product.android.core.expressions;

import org.eclipse.core.expressions.PropertyTester;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.ui.ISelectionService;
import org.eclipse.ui.PlatformUI;

import com.company.product.android.core.ProjectUtils;

public class ProductProjectTester extends PropertyTester {

    public ProductProjectTester() {
        System.out.println("I AM PRODUCT PROJECT TESTER, AND I HAVE BEEN CREATED");
    }

    @Override
    public boolean test(Object receiver, String property, Object[] args,
            Object expectedValue) {
        //IJavaProject project = null;
        //ISelectionService selectionService = 
        //    PlatformUI.getWorkbench().getActiveWorkbenchWindow().getSelectionService();
        //ISelection selection = selectionService.getSelection();
        //boolean enabled = ProjectUtils.isSingleProjectSelected(selection);
        System.out.println("I entered the test method");
        boolean enabled = false;

        System.out.println("The receiver is a " + receiver.getClass().toString());
        IJavaProject project = (IJavaProject)receiver;

        //if (enabled && selection instanceof StructuredSelection) {
            //project = ProjectUtils.getJavaProject();
            if (project != null) {
                enabled = ProjectUtils.hasNeedVersion(project)
                        && (!ProjectUtils.isProductAndroidProject(project.getProject()));

            }
        //}

        return enabled;
    }

}

For the java code, I tried both the current implementation and what is commented out as well. I have tried a lot of different variations that I saw in tutorials that worked for others but not me. The messages are never printed to console, and if i set breakpoints in the constructor or test method, they are never hit. Please let me know if additional information would be useful...

¿Fue útil?

Solución 2

Alright so after 2 days of fighting with this, I was not able to get it to work this way. I followed at least 10 different tutorials on how to get custom property testers to work, but to no avail. I went as far as using the startup extension point to force the plugin to load early. Used a SelectionChangedListener to request updates from the evaluation server anytime the project explorer selection changed. NOTHING seemed like it was going to make the custom property tester work. It simply would not load the property testers... they would never get called by anything, despite everything saying it was set up fine, and perfectly mirror all the tutorials I followed.

Eventually I got tired of trying to make that work and looked for an alternative. What I ended up finding was this: http://blog.eclipse-tips.com/2009/02/commands-part-5-authentication-in-rcp.html

I implemented a SourceProvider to have a variable with values corresponding to different project states. I then use , and check which of the possible values it is. Finally, when the plugin loads, I hook a SelectionChangedListener to the PackageExplorer's viewer, so that any time a selection change occurs, then the logic is reevaluated and that variable is changed if needed. Although it's not the ideal way I wanted to do it, it works, and it's not deprecated. I simply couldn't waste more time trying to get the property testers to work...

Hope this helped someone!

Otros consejos

I use PropertyTester for my Project and it works fine

In your DEFINITIONS XML You do not make a proper reference to your PropertyTester definition:

<definition
    id="com.company.product.android.core.expressions.productProject">
    <with variable="selection">
        <iterate ifEmpty="false">
            <test
               property="com.company.product.android.**core**.expressions.productProjectProperty"
                forcePluginActivation="true">
            </test>
        </iterate>
    </with>
</definition>

Then in your MENU.XML You should make a reference to the right definition (productProject instead of androidProjectNature)

    <menu
           icon="icons/wht_ws.gif"
           id="com.company.product.android.core.tools"
           label="Product Tools">

<visibleWhen>
     <with variable="activeMenuSelection">
          <iterate ifEmpty="false">
               <reference
                     definitionId="com.company.product.android.core.expressions.productProject"/>
          </iterate>
     </with>
</visibleWhen>    

        <command
            commandId="com.company.product.android.core.commands.convertToProduct"
            label="Convert to Product Android Project"
            tooltip="The resources, jars and native library to begin developing an product for Android project application will be added to the Android project.">
        </command>
     </menu>

Finally you don't need the EnableWhen Tag in your HANDLER.XML

I hope this helps

I had a similar issue but wasn't aware of the existence of forcePluginActivation. So I forced the plug-in activation using

/**
 * Necessary to have working menu right from the start
 */
public class Startup implements IStartup {
    @Override
    public void earlyStartup() {
    // this is necessary to have working menu right from the start
}
}

and this extensions :

<extension point="org.eclipse.ui.startup">
    <startup
        class="com.example.package.Startup">
    </startup>
</extension>

I happened to find myself in the exact same situation: everything scrupulously configured to the very detail (so I was convinced and I was true except one thing missing), still it would not call my property tester. Nothing happened at all, no log. So I started debugging down into the abyss of the Eclipse 3.7 runtime environment and found, after three hours of patiently digging, a somewhat surprising error:

java.lang.NoClassDefFoundError: org/eclipse/core/expressions/PropertyTester

Unfortunately it got swallowed again shortly after being raised inside the org.eclipse.core.internal.expressions framework, inside class TypeExtension, with no log whatsoever and not giving any chance to the developer to discover the error without debugging and not even with the Eclipse debug log enabled.

But the nature of the error was straightforward: the plugin containing my property tester was missing the dependency to the Eclipse plugin

org.eclipse.core.expressions

After including it as a required plugin it all seamlessly worked, the property tester was called and the context menu shown properly.

So consider your plugin's dependencies as well while trying to make your property tester work.

Hope this helps.

I was unable to get PropertyTesters working as well. Eventually gave up on them and moved to SourceProviders. Nice writeup on how to implement them here:

How to enable and disable menu items upon condition with using SourceProvider (eclipse rcp Indigo 3.7)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top