/*******************************************************************************
* Copyright (c) 2007, 2014 Gunnar Wagenknecht and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Gunnar Wagenknecht - initial API and implementation
* Mickael Istria (Red Hat Inc) - [102527] Reshaped UI
******************************************************************************/
package org.jboss.tools.playground.naturist;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IProjectNatureDescriptor;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.preference.PreferencePage;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.window.Window;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.ElementListSelectionDialog;
import org.eclipse.ui.dialogs.PropertyPage;
import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
import org.eclipse.ui.internal.progress.ProgressMonitorJobsDialog;
/**
* Project property page for viewing and modifying the project natures.
*
* @since 3.3
*/
public class ProjectNaturesPage extends PropertyPage {
public static final String HELP_CONTEXT_ID = Activator.PLUGIN_ID + ".project_natures_property_page_context"; //$NON-NLS-1$
private IProject project;
private List<String> naturesIdsWorkingCopy;
// widgets
private TableViewer activeNaturesList;
private boolean warningAlreadyShown = false;
/**
* @see PreferencePage#createContents
*/
protected Control createContents(final Composite parent) {
PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(),
HELP_CONTEXT_ID);
Font font = parent.getFont();
Composite composite = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout(1, false);
composite.setLayout(layout);
composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
composite.setFont(font);
initialize();
Composite header = new Composite(composite, SWT.NONE);
header.setLayout(new GridLayout(2, false));
Label description = createDescriptionLabel(header);
description.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 2, 1));
header.setLayout(new GridLayout(2, false));
Label warningImageLabel = new Label(header, SWT.NONE);
warningImageLabel.setImage(header.getDisplay().getSystemImage(SWT.ICON_WARNING));
Label warningLabel = new Label(header, SWT.WRAP);
warningLabel.setText(Messages.ProjectNaturesPage_warningMessage);
GridData warningMessageLayoutData = new GridData(SWT.FILL, SWT.CENTER, true, false);
warningMessageLayoutData.widthHint = 400;
warningMessageLayoutData.verticalIndent = 10;
warningLabel.setLayoutData(warningMessageLayoutData);
Composite naturesComposite = new Composite(composite, SWT.NONE);
naturesComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
naturesComposite.setLayout(new GridLayout(2, false));
this.activeNaturesList = new TableViewer(naturesComposite);
this.activeNaturesList.getTable().setFont(font);
this.activeNaturesList.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
this.activeNaturesList.setLabelProvider(new NatureLabelProvider(this.project.getWorkspace()));
this.activeNaturesList.setContentProvider(new ArrayContentProvider());
try {
this.naturesIdsWorkingCopy = new ArrayList<String>();
this.naturesIdsWorkingCopy.addAll(Arrays.asList(project.getDescription().getNatureIds()));
} catch (CoreException ex) {
Activator.getDefault().getLog().log(new Status(IStatus.WARNING,
Activator.getDefault().getBundle().getSymbolicName(),
"Error while loading project description for " + this.project.getName(), //$NON-NLS-1$
ex));
}
this.activeNaturesList.setInput(this.naturesIdsWorkingCopy);
Composite buttonComposite = new Composite(naturesComposite, SWT.NONE);
buttonComposite.setLayout(new GridLayout(1, false));
buttonComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
Button addButton = new Button(buttonComposite, SWT.PUSH);
addButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false));
addButton.setText(Messages.ProjectNaturesPage_addNature);
addButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
if (!ProjectNaturesPage.this.warningAlreadyShown) {
if (!MessageDialog.openConfirm(getShell(),
Messages.ProjectNaturesPage_changeWarningTitle,
Messages.ProjectNaturesPage_warningMessage + "\n\n" + Messages.ProjectNaturesPage_changeWarningQuestion)) { //$NON-NLS-1$
return;
}
ProjectNaturesPage.this.warningAlreadyShown = true;
}
ElementListSelectionDialog naturesSelectionDialog = new ElementListSelectionDialog(parent.getShell(), new NatureLabelProvider(project.getWorkspace()));
naturesSelectionDialog.setMessage(Messages.ProjectNaturesPage_selectNatureToAddMessage);
naturesSelectionDialog.setTitle(Messages.ProjectNaturesPage_selectNatureToAddTitle);
List<IProjectNatureDescriptor> natures = new ArrayList<IProjectNatureDescriptor>();
for (IProjectNatureDescriptor nature : project.getWorkspace().getNatureDescriptors()) {
if (!naturesIdsWorkingCopy.contains(nature.getNatureId())) {
natures.add(nature);
}
}
naturesSelectionDialog.setElements(natures.toArray(new IProjectNatureDescriptor[natures.size()]));
if (naturesSelectionDialog.open() == Window.OK) {
for (Object item : naturesSelectionDialog.getResult()) {
IProjectNatureDescriptor nature = (IProjectNatureDescriptor) item;
naturesIdsWorkingCopy.add(nature.getNatureId());
}
ProjectNaturesPage.this.activeNaturesList.refresh();
}
}
});
final Button removeButton = new Button(buttonComposite, SWT.PUSH);
removeButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false));
removeButton.setText(Messages.ProjectNaturesPage_removeNature);
removeButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
if (!ProjectNaturesPage.this.warningAlreadyShown) {
if (!MessageDialog.openConfirm(getShell(),
Messages.ProjectNaturesPage_changeWarningTitle,
Messages.ProjectNaturesPage_warningMessage + "\n\n" + Messages.ProjectNaturesPage_changeWarningQuestion)) { //$NON-NLS-1$
return;
}
ProjectNaturesPage.this.warningAlreadyShown = true;
}
IStructuredSelection selection = (IStructuredSelection)ProjectNaturesPage.this.activeNaturesList.getSelection();
for (Object item : selection.toList()) {
String natureId = (String) item;
naturesIdsWorkingCopy.remove(natureId);
}
ProjectNaturesPage.this.activeNaturesList.refresh();
}
});
this.activeNaturesList.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event) {
removeButton.setEnabled(!ProjectNaturesPage.this.activeNaturesList.getSelection().isEmpty());
}
});
this.activeNaturesList.setSelection(new StructuredSelection()); // Empty selection
return composite;
}
private static class NatureLabelProvider extends LabelProvider {
private IWorkspace workspace;
private Map<String, Image> natureImages;
public NatureLabelProvider(IWorkspace workspace) {
this.workspace = workspace;
this.natureImages = new HashMap<String, Image>(workspace.getNatureDescriptors().length);
}
@Override
public String getText(Object element) {
IProjectNatureDescriptor nature = null;
if (element instanceof IProjectNatureDescriptor) {
nature = (IProjectNatureDescriptor) element;
} else if (element instanceof String) {
String natureId = (String) element;
nature = this.workspace.getNatureDescriptor(natureId);
if (nature == null) {
return getMissingNatureLabel(natureId);
}
} else {
return "Not a valid nature input " + element.toString(); //$NON-NLS-1$
}
return getNatureDescriptorLabel(nature);
}
@Override
public Image getImage(Object element) {
String natureId = null;
if (element instanceof IProjectNatureDescriptor) {
natureId = ((IProjectNatureDescriptor) element).getNatureId();
} else if (element instanceof String) {
natureId = (String) element;
} else {
return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJS_ERROR_TSK);
}
if (this.workspace.getNatureDescriptor(natureId) != null) {
if (!natureImages.containsKey(natureId)) {
ImageDescriptor image = IDEWorkbenchPlugin.getDefault().getProjectImageRegistry().getNatureImage(natureId);
if (image != null) {
this.natureImages.put(natureId, image.createImage());
} else {
// TODO a generic image?
}
}
return natureImages.get(natureId);
} else /* Unknown nature*/ {
return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJS_WARN_TSK);
}
}
protected String getMissingNatureLabel(String natureId) {
return NLS.bind(
Messages.ProjectNaturesPage_missingNatureText,
natureId);
}
protected String getNatureDescriptorLabel(
IProjectNatureDescriptor natureDescriptor) {
String label = natureDescriptor.getLabel();
if (label.trim().length() == 0)
return natureDescriptor.getNatureId();
return label;
}
@Override
public void dispose() {
for (Image image : natureImages.values()) {
image.dispose();
}
super.dispose();
}
}
// private ViewerComparator getViewerComperator() {
// return new ViewerComparator(new Comparator() {
//
// public int compare(Object element1, Object element2) {
// int val1 = 0;
// int val2 = 0;
//
// if (element1 instanceof IProjectNatureDescriptor) {
// element1 = getNatureDescriptorLabel((IProjectNatureDescriptor) element1);
// } else {
// val1 += element1.getClass().hashCode();
// }
// if (element2 instanceof IProjectNatureDescriptor) {
// element2 = getNatureDescriptorLabel((IProjectNatureDescriptor) element1);
// } else {
// val2 += element2.getClass().hashCode();
// }
//
// int result = val1 - val2;
// if (result != 0)
// return result;
//
// return String.valueOf(element1).compareTo(
// String.valueOf(element2));
// }
//
// });
// }
/**
* Handle the exception thrown when saving.
*
* @param e
* the exception
*/
protected void handle(InvocationTargetException e) {
IStatus error;
Throwable target = e.getTargetException();
if (target instanceof CoreException) {
error = ((CoreException) target).getStatus();
} else {
String msg = target.getMessage();
if (msg == null) {
msg = IDEWorkbenchMessages.Internal_error;
}
error = new Status(IStatus.ERROR, IDEWorkbenchPlugin.IDE_WORKBENCH,
1, msg, target);
}
ErrorDialog.openError(getControl().getShell(), null, null, error);
}
/**
* Initializes a ProjectReferencePage.
*/
private void initialize() {
project = (IProject) getElement().getAdapter(IResource.class);
noDefaultAndApplyButton();
setDescription(Messages.ProjectNaturesPage_label);
}
/**
* @see PreferencePage#performOk
*/
public boolean performOk() {
List<String> originalNatureIds = null;
try {
originalNatureIds = Arrays.asList(this.project.getDescription().getNatureIds());
} catch (CoreException ex) {
Activator.getDefault().getLog().log(new Status(IStatus.WARNING,
Activator.getDefault().getBundle().getSymbolicName(),
"Error while loading project description for " + this.project.getName(), //$NON-NLS-1$
ex));
originalNatureIds = new ArrayList<String>();
}
if (this.naturesIdsWorkingCopy.size() == originalNatureIds.size()
&& this.naturesIdsWorkingCopy.containsAll(originalNatureIds)) {
return true;
}
// set nature ids
IRunnableWithProgress runnable = new IRunnableWithProgress() {
public void run(IProgressMonitor monitor)
throws InvocationTargetException {
try {
IProjectDescription description = project.getDescription();
description.setNatureIds(ProjectNaturesPage.this.naturesIdsWorkingCopy.toArray(new String[ProjectNaturesPage.this.naturesIdsWorkingCopy.size()]));
project.setDescription(description, monitor);
} catch (CoreException e) {
throw new InvocationTargetException(e);
}
}
};
try {
new ProgressMonitorJobsDialog(getControl().getShell()).run(true,
true, runnable);
} catch (InterruptedException e) {
// Ignore interrupted exceptions
} catch (InvocationTargetException e) {
handle(e);
return false;
}
return true;
}
}