package net.certware.core.ui.contributions;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import net.certware.core.ui.CertWareUI;
import net.certware.core.ui.log.CertWareLog;
import net.certware.core.ui.natures.ProjectNature;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.action.ContributionItem;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MenuAdapter;
import org.eclipse.swt.events.MenuEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
/**
* Contributes a dynamic menu item for toggling application of the project nature.
* @author mrb
* @since 1.1.0
*/
public class ToggleProjectNature extends ContributionItem
{
/**
* Constructor creates image reference.
*/
public ToggleProjectNature() {
}
/**
* Constructor creates image reference.
* @param id
*/
public ToggleProjectNature(String id) {
super(id);
}
/**
* Disposes of the parent and the image reference.
*/
public void dispose() {
super.dispose();
}
/**
* Fills the menu, adding a menu item for toggling the nature.
* Adds a selection listener to the item.
* Adds a menu listener to the menu to update its state.
*/
public void fill(Menu menu, int index) {
final MenuItem menuItem = new MenuItem(menu, SWT.CHECK, index);
Image menuImage = CertWareUI.getDefault().getImageRegistry().get(CertWareUI.CERTWARE_IMAGE);
menuItem.setText("Toggle CertWare nature");
menuItem.setImage(menuImage);
menuItem.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent se) {
run();
}
});
menu.addMenuListener(new MenuAdapter() {
public void menuShown(MenuEvent me) {
updateState(menuItem);
}
});
}
/**
* Updates the enable and selection states of the menu item.
* Enabled if one or more projects selected.
* Selected if enabled and project has nature applied.
* @param menuItem
*/
protected void updateState(MenuItem menuItem) {
Collection<IProject> projects = getSelectedProjects();
boolean enabled = projects.size() > 0;
menuItem.setEnabled(enabled);
menuItem.setSelection(enabled && ProjectNature.hasNature(projects.iterator().next()));
}
/**
* Creates a collection of open projects in the selection.
* Adapts resources if possible.
* @return collection of open projects, possibly empty
*/
private Collection<IProject> getSelectedProjects() {
Collection<IProject> projects = new HashSet<IProject>();
IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
ISelection selection = window.getActivePage().getSelection();
if ( selection instanceof IStructuredSelection ) {
for (Iterator<?> iter = ((IStructuredSelection)selection).iterator(); iter.hasNext(); ) {
Object e = iter.next();
if ( ! (e instanceof IResource)) {
if ( !(e instanceof IAdaptable))
continue;
e = ((IAdaptable)e).getAdapter(IResource.class);
if ( ! (e instanceof IResource))
continue;
}
if ( ! (e instanceof IProject)) {
e = ((IResource)e).getProject();
if ( ! (e instanceof IProject))
continue;
}
IProject p = (IProject)e;
if ( p.isOpen() )
projects.add((IProject)e);
}
}
return projects;
}
/**
* Performs the nature toggle, calling {@code toggleNature} on the collection
* returned by {@code getSelectedProjects}. Performed in a workspace runnable.
* Catches {@ CoreException} and writes to CertWare log.
*/
protected void run() {
IWorkspace workspace = ResourcesPlugin.getWorkspace();
try {
workspace.run(
new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
Collection<IProject> projects = getSelectedProjects();
for (IProject p : projects ) {
toggleNature(p);
}
}},null);
}
catch (CoreException ce) {
CertWareLog.logError("Toggle CertWare nature", ce);
}
}
/**
* Toggles the nature on the given.
* If project has nature, remove it. If project does not have nature, add it.
* @param project project reference
* @throws CoreException if project description cannot be read or written
*/
private void toggleNature(IProject project) throws CoreException {
if ( ProjectNature.hasNature(project) )
ProjectNature.removeNature(project);
else
ProjectNature.addNature(project);
}
}