views:

104

answers:

3

What I'm trying to achieve is to contribute an action to the IProject pop up menu. The action is defined like this in my plugin.xml:

   <extension
         point="org.eclipse.ui.popupMenus">
      <objectContribution
            adaptable="true"
            objectClass="org.eclipse.core.resources.IProject"
            nameFilter="*"
            id="RemoteSync.contribution1">
         <action
               label="Enable RemoteSync"
               class="remotesync.builder.ToggleNatureAction"
               menubarPath="additions"
               enablesFor="1"
               id="RemoteSync.addRemoveNatureAction"
               style="toggle">
         </action>
      </objectContribution>
   </extension>

On run() I do setPersistentProperty() in order to save the menu toggle state and I want to restore that later when the plug in starts or whenever the pop up menu is displayed on setActivePart().

Here are the relevant pieces of code:

public void run(IAction action) {
    if (selection instanceof IStructuredSelection) {
        for (Iterator it = ((IStructuredSelection) selection).iterator(); it
                .hasNext();) {
            Object element = it.next();
            IProject project = null;
            if (element instanceof IProject) {
                project = (IProject) element;
            } else if (element instanceof IAdaptable) {
                project = (IProject) ((IAdaptable) element)
                        .getAdapter(IProject.class);
            }
            if (project != null) {
                toggleNature(project);
                try {
                    ((IResource) project).setPersistentProperty(
                            new QualifiedName("", ENABLED_PROPERTY), new Boolean(action.isChecked()).toString());
                } catch (CoreException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }
}


public void setActivePart(IAction action, IWorkbenchPart targetPart) {
    if (selection instanceof IStructuredSelection) {
        for (Iterator it = ((IStructuredSelection) selection).iterator(); it
                .hasNext();) {
            Object element = it.next();
            IProject project = null;
            if (element instanceof IProject) {
                project = (IProject) element;
            } else if (element instanceof IAdaptable) {
                project = (IProject) ((IAdaptable) element)
                        .getAdapter(IProject.class);
            }
            if (project != null) {
                toggleNature(project);
                try {
                    String status = ((IResource) project).getPersistentProperty(
                            new QualifiedName("", ENABLED_PROPERTY));
                    action.setChecked(new Boolean(status));
                } catch (CoreException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }
}

Everything works as expected but one thing - when the IProject context menu is first activated it does not reflect the saved state, but if I bring the menu up again it shows the saved state as expected. Then if I bring the menu up for another project it once again shows with incorrect state, but the second time works fine.

A: 

well, take a look at these lines

            String status = ((IResource) project).getPersistentProperty(
                        new QualifiedName("", ENABLED_PROPERTY));

      ((IResource) project).setPersistentProperty(
                        new QualifiedName("", ENABLED_PROPERTY), new Boolean(action.isChecked()).toString());

The variable 'project' points to the selected project and therefore the state is only stored in its meta data. if you want to store the state independant of the project, a solution might be storing them in the workspace metadata.

javalympics
I want to store the menu toggle state on per project basis.The problem is when the IProject context menu is first activated it does not reflect the saved state, but if I bring the menu up again it shows the saved state as expected. Then if I bring the menu up for another project it once again shows with incorrect state, but the second time works fine.
blablacio
A: 

Well, it seems there is either a problem with my code or bug/feature in Eclipse 3.6 I20100608-0911 which prevents selectionChanged() from firing properly the first time you click on resource (IProject in my case):

public void selectionChanged(IAction action, ISelection selection) {
    this.selection = selection;
}

As I found out events are fired in this order when bringing up the context menu for the first time:

  1. selectionChanged()
  2. setActivePart()
  3. selectionChanged()

The ISelection passed to selectionChanged() the first time is always "empty selection".

After the first time, bringing the context menu yields the following order in which events are fired:

  1. setActivePart()
  2. selectionChanged()

That's why we should fire selectionChanged() every time inside setActivePart() in order to make sure we get the most recent selection:

public void setActivePart(IAction action, IWorkbenchPart targetPart) {
    selectionChanged(action, targetPart.getSite().getPage().getSelection());
    ...
}

I hope that helps someone ;)

blablacio
A: 

Yes.It has surely helped me.Was wondering how i ll be getting my solution all this while :)

pria