blob: e0de05df7774d6a6afbd0c9f7e401f28f2b78bab [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2011 IBM Corporation 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
*******************************************************************************/
package org.eclipse.pde.api.tools.ui.internal.wizards;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
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.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.ltk.core.refactoring.CompositeChange;
import org.eclipse.ltk.core.refactoring.TextFileChange;
import org.eclipse.ltk.core.refactoring.resource.DeleteResourceChange;
import org.eclipse.ltk.ui.refactoring.UserInputWizardPage;
import org.eclipse.pde.api.tools.internal.ApiDescriptionProcessor;
import org.eclipse.pde.api.tools.internal.IApiCoreConstants;
import org.eclipse.pde.api.tools.internal.provisional.ApiPlugin;
import org.eclipse.pde.api.tools.internal.util.Util;
import org.eclipse.pde.api.tools.ui.internal.ApiUIPlugin;
import org.eclipse.pde.api.tools.ui.internal.IApiToolsConstants;
import org.eclipse.pde.api.tools.ui.internal.IApiToolsHelpContextIds;
import org.eclipse.pde.api.tools.ui.internal.SWTFactory;
import org.eclipse.pde.api.tools.ui.internal.StringMatcher;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.TextEdit;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchSite;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.model.WorkbenchLabelProvider;
import org.eclipse.ui.progress.UIJob;
import org.eclipse.ui.progress.WorkbenchJob;
import com.ibm.icu.text.MessageFormat;
/**
* The main page for the {@link ApiToolingSetupWizard}
*
* @since 1.0.0
*/
public class ApiToolingSetupWizardPage extends UserInputWizardPage {
/**
* Job for updating the filtering on the table viewer
*/
class UpdateJob extends WorkbenchJob {
private String pattern = null;
/**
* Constructor
*/
public UpdateJob() {
super(WizardMessages.ApiToolingSetupWizardPage_filter_update_job);
setSystem(true);
}
/**
* Sets the current text filter to use
* @param filter
*/
public synchronized void setFilter(String pattern) {
this.pattern = pattern;
}
/**
* @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor)
*/
public IStatus runInUIThread(IProgressMonitor monitor) {
if(tableviewer != null) {
try {
tableviewer.getTable().setRedraw(false);
synchronized (this) {
filter.setPattern(pattern + '*');
}
tableviewer.refresh(true);
tableviewer.setCheckedElements(checkedset.toArray());
}
finally {
tableviewer.getTable().setRedraw(true);
}
}
return Status.OK_STATUS;
}
}
/**
* Filter for the viewer, uses a text matcher
*/
static class StringFilter extends ViewerFilter {
private String pattern = null;
StringMatcher matcher = null;
public void setPattern(String pattern) {
this.pattern = pattern;
}
/**
* @see org.eclipse.jface.viewers.ViewerFilter#select(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
*/
public boolean select(Viewer viewer, Object parentElement, Object element) {
if(pattern == null) {
return true;
}
if(pattern.trim().length() == 0) {
return true;
}
String name = null;
if(element instanceof IResource) {
name = ((IResource)element).getName();
}
if(name == null) {
return false;
}
matcher = new StringMatcher(pattern, true, false);
return matcher.match(name, 0, name.length());
}
}
private static final String SETTINGS_SECTION = "ApiToolingSetupWizardPage"; //$NON-NLS-1$
private static final String SETTINGS_REMOVECXML = "remove_componentxml"; //$NON-NLS-1$
CheckboxTableViewer tableviewer = null;
HashSet checkedset = new HashSet();
Button removecxml = null;
UpdateJob updatejob = new UpdateJob();
StringFilter filter = new StringFilter();
private Text checkcount = null;
/**
* Constructor
* @param pageName
*/
protected ApiToolingSetupWizardPage() {
super(WizardMessages.UpdateJavadocTagsWizardPage_4);
setTitle(WizardMessages.UpdateJavadocTagsWizardPage_4);
setMessage(WizardMessages.UpdateJavadocTagsWizardPage_7);
}
/* (non-Javadoc)
* @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
*/
public void createControl(Composite parent) {
Composite comp = SWTFactory.createComposite(parent, 1, 1, GridData.FILL_BOTH);
setControl(comp);
PlatformUI.getWorkbench().getHelpSystem().setHelp(comp, IApiToolsHelpContextIds.API_TOOLING_SETUP_WIZARD_PAGE);
SWTFactory.createWrapLabel(comp, WizardMessages.UpdateJavadocTagsWizardPage_6, 1, 100);
SWTFactory.createVerticalSpacer(comp, 1);
SWTFactory.createWrapLabel(comp, WizardMessages.ApiToolingSetupWizardPage_6, 1, 50);
final Text text = SWTFactory.createText(comp, SWT.BORDER, 1);
text.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
updatejob.setFilter(text.getText().trim());
updatejob.cancel();
updatejob.schedule();
}
});
text.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
if (e.keyCode == SWT.ARROW_DOWN) {
if(tableviewer != null) {
tableviewer.getTable().setFocus();
}
}
}
});
SWTFactory.createWrapLabel(comp, WizardMessages.UpdateJavadocTagsWizardPage_8, 1, 50);
Table table = new Table(comp, SWT.BORDER | SWT.FULL_SELECTION | SWT.CHECK | SWT.MULTI);
GridData gd = new GridData(GridData.FILL_BOTH);
gd.heightHint = 150;
table.setLayoutData(gd);
tableviewer = new CheckboxTableViewer(table);
tableviewer.setLabelProvider(new WorkbenchLabelProvider());
tableviewer.setContentProvider(new ArrayContentProvider());
tableviewer.setInput(getInputProjects());
tableviewer.setComparator(new ViewerComparator());
tableviewer.addFilter(filter);
tableviewer.addCheckStateListener(new ICheckStateListener() {
public void checkStateChanged(CheckStateChangedEvent event) {
if(event.getChecked()) {
checkedset.add(event.getElement());
}
else {
checkedset.remove(event.getElement());
}
setPageComplete(pageValid());
}
});
Composite bcomp = SWTFactory.createComposite(comp, 3, 1, GridData.FILL_HORIZONTAL | GridData.END, 0, 0);
Button button = SWTFactory.createPushButton(bcomp, WizardMessages.UpdateJavadocTagsWizardPage_10, null);
button.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
tableviewer.setAllChecked(true);
checkedset.addAll(Arrays.asList(tableviewer.getCheckedElements()));
setPageComplete(pageValid());
}
});
button = SWTFactory.createPushButton(bcomp, WizardMessages.UpdateJavadocTagsWizardPage_11, null);
button.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
tableviewer.setAllChecked(false);
TableItem[] items = tableviewer.getTable().getItems();
for(int i = 0; i < items.length; i++) {
checkedset.remove(items[i].getData());
}
setPageComplete(pageValid());
}
});
checkcount = SWTFactory.createText(bcomp, SWT.FLAT | SWT.READ_ONLY, 1, GridData.HORIZONTAL_ALIGN_END | GridData.GRAB_HORIZONTAL);
checkcount.setBackground(bcomp.getBackground());
Object[] selected = getWorkbenchSelection();
if(selected.length > 0) {
tableviewer.setCheckedElements(selected);
checkedset.addAll(Arrays.asList(selected));
}
setPageComplete(checkedset.size() > 0);
SWTFactory.createVerticalSpacer(comp, 1);
removecxml = SWTFactory.createCheckButton(comp, WizardMessages.ApiToolingSetupWizardPage_0, null, true, 1);
IDialogSettings settings = ApiUIPlugin.getDefault().getDialogSettings().getSection(SETTINGS_SECTION);
if(settings != null) {
removecxml.setSelection(settings.getBoolean(SETTINGS_REMOVECXML));
}
}
/**
* @see org.eclipse.jface.wizard.WizardPage#setPageComplete(boolean)
*/
public void setPageComplete(boolean complete) {
super.setPageComplete(complete);
updateCheckStatus(checkedset.size());
}
/**
* Updates the number of items that have been checked
* @param count
*/
private void updateCheckStatus(int count) {
if(checkcount == null) {
return;
}
checkcount.setText(MessageFormat.format(WizardMessages.ApiToolingSetupWizardPage_n_items_checked, new String[] {Integer.toString(count)}));
}
/**
* @return the complete listing of projects in the workspace that could have API Tools set-up
* on them
* @throws CoreException
*/
private IProject[] getInputProjects() {
IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
ArrayList pjs = new ArrayList();
for(int i = 0; i < projects.length; i++) {
try {
IProject project = projects[i];
if(acceptProject(project)) {
pjs.add(project);
}
}
catch(CoreException ce) {}
}
return (IProject[]) pjs.toArray(new IProject[pjs.size()]);
}
private boolean acceptProject(IProject project) throws CoreException {
if(project == null) {
return false;
}
return (project.hasNature(JavaCore.NATURE_ID) && project.hasNature("org.eclipse.pde.PluginNature")) //$NON-NLS-1$
&& !project.hasNature(ApiPlugin.NATURE_ID)
&& !Util.isBinaryProject(project);
}
/**
* @return the current selection from the workbench as an array of objects
*/
protected Object[] getWorkbenchSelection() {
IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
if(window != null) {
IWorkbenchPage page = window.getActivePage();
if(page != null) {
IWorkbenchPart part = page.getActivePart();
if(part != null) {
IWorkbenchSite site = part.getSite();
if(site != null) {
ISelectionProvider provider = site.getSelectionProvider();
if(provider != null) {
ISelection selection = provider.getSelection();
if(selection instanceof IStructuredSelection) {
Object[] jps = ((IStructuredSelection)provider.getSelection()).toArray();
ArrayList pjs = new ArrayList();
for(int i = 0; i < jps.length; i++) {
if(jps[i] instanceof IAdaptable) {
IAdaptable adapt = (IAdaptable) jps[i];
IProject pj = (IProject) adapt.getAdapter(IProject.class);
try {
if(acceptProject(pj)) {
pjs.add(pj);
}
}
catch(CoreException ce){}
}
}
return pjs.toArray();
}
}
}
}
}
}
return new Object[0];
}
/**
* @return if the page is valid or not, this method also sets error messages
*/
protected boolean pageValid() {
if(checkedset.size() < 1) {
setErrorMessage(WizardMessages.UpdateJavadocTagsWizardPage_12);
return false;
}
setErrorMessage(null);
return true;
}
/* (non-Javadoc)
* @see org.eclipse.ltk.ui.refactoring.UserInputWizardPage#getNextPage()
*/
public IWizardPage getNextPage() {
//always have to collect changes again in the event the user goes back and forth,
//as a change cannot ever have more than one parent - EVER
collectChanges();
IWizardPage page = super.getNextPage();
if (page != null) {
page.setDescription(WizardMessages.ApiToolingSetupWizardPage_5);
}
return page;
}
/**
* Creates all of the text edit changes collected from the processor. The collected edits are arranged as multi-edits
* for the one file that they belong to
* @param projectchange
* @param project
* @param cxml
*/
void createTagChanges(CompositeChange projectchange, IJavaProject project, File cxml) {
try {
HashMap map = new HashMap();
ApiDescriptionProcessor.collectTagUpdates(project, cxml, map);
IFile file = null;
TextFileChange change = null;
MultiTextEdit multiedit = null;
HashSet alledits = null;
TextEdit edit = null;
for(Iterator iter = map.entrySet().iterator(); iter.hasNext();) {
Map.Entry entry = (Map.Entry) iter.next();
file = (IFile) entry.getKey();
change = new TextFileChange(MessageFormat.format(WizardMessages.JavadocTagRefactoring_2, new String[] {file.getName()}), file);
multiedit = new MultiTextEdit();
change.setEdit(multiedit);
alledits = (HashSet) entry.getValue();
if(alledits != null) {
for(Iterator iter2 = alledits.iterator(); iter2.hasNext();) {
edit = (TextEdit) iter2.next();
multiedit.addChild(edit);
}
}
if(change != null) {
projectchange.add(change);
}
}
}
catch (CoreException e) {
ApiUIPlugin.log(e);
}
catch (IOException e) {
ApiUIPlugin.log(e);
}
}
/**
* @return the mapping of text edits to the IFile they occur on
*/
private void collectChanges() {
final ApiToolingSetupRefactoring refactoring = (ApiToolingSetupRefactoring) getRefactoring();
IRunnableWithProgress op = new IRunnableWithProgress() {
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
Object[] projects = checkedset.toArray(new IProject[checkedset.size()]);
IProject project = null;
SubMonitor localmonitor = SubMonitor.convert(monitor);
localmonitor.beginTask(IApiToolsConstants.EMPTY_STRING, projects.length);
localmonitor.setTaskName(WizardMessages.ApiToolingSetupWizardPage_7);
refactoring.resetRefactoring();
boolean remove = removecxml.getSelection();
CompositeChange pchange = null;
for(int i = 0; i < projects.length; i++) {
project = (IProject) projects[i];
pchange = new CompositeChange(project.getName());
refactoring.addChange(pchange);
pchange.add(new ProjectUpdateChange(project));
localmonitor.subTask(MessageFormat.format(WizardMessages.ApiToolingSetupWizardPage_4, new String[] {project.getName()}));
IResource cxml = project.findMember(IApiCoreConstants.COMPONENT_XML_NAME);
if(cxml != null) {
//collect the changes for doc
createTagChanges(pchange, JavaCore.create(project), new File(cxml.getLocationURI()));
if(remove) {
pchange.add(new DeleteResourceChange(cxml.getFullPath(), true));
}
}
Util.updateMonitor(localmonitor, 1);
}
}
};
try {
getContainer().run(false, false, op);
} catch (InvocationTargetException e) {
ApiUIPlugin.log(e);
} catch (InterruptedException e) {
ApiUIPlugin.log(e);
}
}
/* (non-Javadoc)
* @see org.eclipse.ltk.ui.refactoring.UserInputWizardPage#performFinish()
*/
protected boolean performFinish() {
collectChanges();
return super.performFinish();
}
/**
* Called by the {@link ApiToolingSetupWizard} when finishing the wizard
*
* @return true if the page finished normally, false otherwise
*/
public boolean finish() {
IDialogSettings settings = ApiUIPlugin.getDefault().getDialogSettings().addNewSection(SETTINGS_SECTION);
settings.put(SETTINGS_REMOVECXML, removecxml.getSelection());
notifyNoDefaultProfile();
return true;
}
/**
* Notifies the user that they have no default API profile
*/
private void notifyNoDefaultProfile() {
if(ApiPlugin.getDefault().getApiBaselineManager().getDefaultApiBaseline() == null) {
UIJob job = new UIJob("No default API profile detected") { //$NON-NLS-1$
public IStatus runInUIThread(IProgressMonitor monitor) {
boolean doit = MessageDialog.openQuestion(getShell(), WizardMessages.ApiToolingSetupWizardPage_1, WizardMessages.ApiToolingSetupWizardPage_2 +
WizardMessages.ApiToolingSetupWizardPage_3);
if(doit) {
SWTFactory.showPreferencePage(getShell(), IApiToolsConstants.ID_BASELINES_PREF_PAGE, null);
}
return Status.OK_STATUS;
}
};
job.setSystem(true);
job.schedule();
}
}
}