blob: 2d063350dd3bf038b13703cdf9fa4a348a010d43 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 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.jdt.internal.ui.fix;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.xml.sax.InputSource;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
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.Link;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.core.resources.ProjectScope;
import org.eclipse.jface.dialogs.ControlEnableState;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.viewers.ColumnLayoutData;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.jface.window.Window;
import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.ui.dialogs.PreferencesUtil;
import org.eclipse.ltk.ui.refactoring.RefactoringWizard;
import org.eclipse.ltk.ui.refactoring.UserInputWizardPage;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.internal.corext.fix.CleanUpConstants;
import org.eclipse.jdt.internal.corext.fix.CleanUpPreferenceUtil;
import org.eclipse.jdt.internal.corext.fix.CleanUpRefactoring;
import org.eclipse.jdt.internal.corext.fix.CleanUpRegistry.CleanUpTabPageDescriptor;
import org.eclipse.jdt.internal.corext.util.Messages;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jdt.ui.cleanup.CleanUpOptions;
import org.eclipse.jdt.ui.cleanup.ICleanUp;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.JavaPluginImages;
import org.eclipse.jdt.internal.ui.preferences.BulletListBlock;
import org.eclipse.jdt.internal.ui.preferences.CleanUpPreferencePage;
import org.eclipse.jdt.internal.ui.preferences.cleanup.CleanUpProfileVersioner;
import org.eclipse.jdt.internal.ui.preferences.cleanup.CleanUpTabPage;
import org.eclipse.jdt.internal.ui.preferences.formatter.IModifyDialogTabPage;
import org.eclipse.jdt.internal.ui.preferences.formatter.ProfileManager;
import org.eclipse.jdt.internal.ui.preferences.formatter.ProfileManager.CustomProfile;
import org.eclipse.jdt.internal.ui.preferences.formatter.ProfileManager.Profile;
import org.eclipse.jdt.internal.ui.preferences.formatter.ProfileStore;
import org.eclipse.jdt.internal.ui.util.SWTUtil;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.DialogField;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.IDialogFieldListener;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.IListAdapter;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.ListDialogField;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.SelectionButtonDialogField;
public class CleanUpRefactoringWizard extends RefactoringWizard {
private static final String USE_CUSTOM_PROFILE_KEY= "org.eclipse.jdt.ui.cleanup.use_dialog_profile"; //$NON-NLS-1$
private static final String CUSTOM_PROFILE_KEY= "org.eclipse.jdt.ui.cleanup.custom_profile"; //$NON-NLS-1$
private static class ProjectProfileLableProvider extends LabelProvider implements ITableLabelProvider {
private Hashtable<String, Profile> fProfileIdsTable;
/**
* {@inheritDoc}
*/
public Image getColumnImage(Object element, int columnIndex) {
return null;
}
/**
* {@inheritDoc}
*/
public String getColumnText(Object element, int columnIndex) {
if (columnIndex == 0) {
return ((IJavaProject)element).getProject().getName();
} else if (columnIndex == 1) {
if (fProfileIdsTable == null)
fProfileIdsTable= loadProfiles();
IEclipsePreferences instancePreferences= InstanceScope.INSTANCE.getNode(JavaUI.ID_PLUGIN);
final String workbenchProfileId;
if (instancePreferences.get(CleanUpConstants.CLEANUP_PROFILE, null) != null) {
workbenchProfileId= instancePreferences.get(CleanUpConstants.CLEANUP_PROFILE, null);
} else {
workbenchProfileId= CleanUpConstants.DEFAULT_PROFILE;
}
return getProjectProfileName((IJavaProject)element, fProfileIdsTable, workbenchProfileId);
}
return null;
}
private Hashtable<String, Profile> loadProfiles() {
List<Profile> list= CleanUpPreferenceUtil.loadProfiles(InstanceScope.INSTANCE);
Hashtable<String, Profile> profileIdsTable= new Hashtable<String, Profile>();
for (Iterator<Profile> iterator= list.iterator(); iterator.hasNext();) {
Profile profile= iterator.next();
profileIdsTable.put(profile.getID(), profile);
}
return profileIdsTable;
}
private String getProjectProfileName(final IJavaProject project, Hashtable<String, Profile> profileIdsTable, String workbenchProfileId) {
ProjectScope projectScope= new ProjectScope(project.getProject());
IEclipsePreferences node= projectScope.getNode(JavaUI.ID_PLUGIN);
String id= node.get(CleanUpConstants.CLEANUP_PROFILE, null);
if (id == null) {
Profile profile= profileIdsTable.get(workbenchProfileId);
if (profile != null) {
return profile.getName();
} else {
return MultiFixMessages.CleanUpRefactoringWizard_unknownProfile_Name;
}
} else {
Profile profile= profileIdsTable.get(id);
if (profile != null) {
return profile.getName();
} else {
return Messages.format(MultiFixMessages.CleanUpRefactoringWizard_UnmanagedProfileWithName_Name, id.substring(ProfileManager.ID_PREFIX.length()));
}
}
}
public void reset() {
fProfileIdsTable= null;
}
}
private static class CleanUpConfigurationPage extends UserInputWizardPage implements IModifyDialogTabPage.IModificationListener {
private static final class WizardCleanUpSelectionDialog extends CleanUpSelectionDialog {
private static final String CLEAN_UP_SELECTION_PREFERENCE_KEY= "clean_up_selection_dialog"; //$NON-NLS-1$
private WizardCleanUpSelectionDialog(Shell parent, Map<String, String> settings) {
super(parent, settings, MultiFixMessages.CleanUpRefactoringWizard_CustomCleanUpsDialog_title);
}
@Override
protected NamedCleanUpTabPage[] createTabPages(Map<String, String> workingValues) {
CleanUpTabPageDescriptor[] descriptors= JavaPlugin.getDefault().getCleanUpRegistry().getCleanUpTabPageDescriptors(CleanUpConstants.DEFAULT_CLEAN_UP_OPTIONS);
NamedCleanUpTabPage[] result= new NamedCleanUpTabPage[descriptors.length];
for (int i= 0; i < descriptors.length; i++) {
String name= descriptors[i].getName();
CleanUpTabPage page= descriptors[i].createTabPage();
page.setOptionsKind(CleanUpConstants.DEFAULT_CLEAN_UP_OPTIONS);
page.setModifyListener(this);
page.setWorkingValues(workingValues);
result[i]= new NamedCleanUpTabPage(name, page);
}
return result;
}
@Override
protected String getPreferenceKeyPrefix() {
return CLEAN_UP_SELECTION_PREFERENCE_KEY;
}
@Override
protected String getSelectionCountMessage(int selectionCount, int size) {
return Messages.format(MultiFixMessages.CleanUpRefactoringWizard_XofYCleanUpsSelected_message, new Object[] {new Integer(selectionCount), new Integer(size)});
}
@Override
protected String getEmptySelectionMessage() {
return MultiFixMessages.CleanUpRefactoringWizard_EmptySelection_message;
}
}
private static final class ProfileTableAdapter implements IListAdapter<IJavaProject> {
private final ProjectProfileLableProvider fProvider;
private final Shell fShell;
private ProfileTableAdapter(ProjectProfileLableProvider provider, Shell shell) {
fProvider= provider;
fShell= shell;
}
public void customButtonPressed(ListDialogField<IJavaProject> field, int index) {
openPropertyDialog(field);
}
public void doubleClicked(ListDialogField<IJavaProject> field) {
openPropertyDialog(field);
}
private void openPropertyDialog(ListDialogField<IJavaProject> field) {
IJavaProject project= field.getSelectedElements().get(0);
PreferencesUtil.createPropertyDialogOn(fShell, project, CleanUpPreferencePage.PROP_ID, null, null).open();
List<?> selectedElements= field.getSelectedElements();
fProvider.reset();
field.refresh();
field.selectElements(new StructuredSelection(selectedElements));
}
public void selectionChanged(ListDialogField<IJavaProject> field) {
if (field.getSelectedElements().size() != 1) {
field.enableButton(0, false);
} else {
field.enableButton(0, true);
}
}
}
private static final String ENCODING= "UTF-8"; //$NON-NLS-1$
private final CleanUpRefactoring fCleanUpRefactoring;
private Map<String, String> fCustomSettings;
private SelectionButtonDialogField fUseCustomField;
private ControlEnableState fEnableState;
public CleanUpConfigurationPage(CleanUpRefactoring refactoring) {
super(MultiFixMessages.CleanUpRefactoringWizard_CleanUpConfigurationPage_title);
fCleanUpRefactoring= refactoring;
int cleanUpTargetsSize= fCleanUpRefactoring.getCleanUpTargetsSize();
IJavaProject[] projects= fCleanUpRefactoring.getProjects();
if (cleanUpTargetsSize == 1) {
setMessage(MultiFixMessages.CleanUpRefactoringWizard_CleaningUp11_Title);
} else if (projects.length == 1) {
setMessage(Messages.format(MultiFixMessages.CleanUpRefactoringWizard_CleaningUpN1_Title, new Integer(cleanUpTargetsSize)));
} else {
setMessage(Messages.format(MultiFixMessages.CleanUpRefactoringWizard_CleaningUpNN_Title, new Object[] {new Integer(cleanUpTargetsSize), new Integer(projects.length)}));
}
}
/**
* {@inheritDoc}
*/
public void createControl(Composite parent) {
initializeDialogUnits(parent);
boolean isCustom= getDialogSettings().getBoolean(USE_CUSTOM_PROFILE_KEY);
final Composite composite= new Composite(parent, SWT.NONE);
composite.setLayout(new GridLayout(2, false));
composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
composite.setFont(parent.getFont());
SelectionButtonDialogField useProfile= new SelectionButtonDialogField(SWT.RADIO);
useProfile.setLabelText(MultiFixMessages.CleanUpRefactoringWizard_use_configured_radio);
useProfile.setSelection(!isCustom);
useProfile.doFillIntoGrid(composite, 2);
ProjectProfileLableProvider tableLabelProvider= new ProjectProfileLableProvider();
IListAdapter<IJavaProject> listAdapter= new ProfileTableAdapter(tableLabelProvider, getShell());
String[] buttons= new String[] {
MultiFixMessages.CleanUpRefactoringWizard_Configure_Button
};
final ListDialogField<IJavaProject> settingsField= new ListDialogField<IJavaProject>(listAdapter, buttons, tableLabelProvider) {
/**
* {@inheritDoc}
*/
@Override
protected int getListStyle() {
return super.getListStyle() | SWT.SINGLE;
}
};
String[] headerNames= new String[] {
MultiFixMessages.CleanUpRefactoringWizard_Project_TableHeader,
MultiFixMessages.CleanUpRefactoringWizard_Profile_TableHeader
};
ColumnLayoutData[] columns = new ColumnLayoutData[] {
new ColumnWeightData(2, true),
new ColumnWeightData(1, true)
};
settingsField.setTableColumns(new ListDialogField.ColumnsDescription(columns , headerNames, true));
settingsField.setViewerComparator(new ViewerComparator());
settingsField.doFillIntoGrid(composite, 3);
Table table= settingsField.getTableViewer().getTable();
GridData data= (GridData)settingsField.getListControl(null).getLayoutData();
data.horizontalIndent= 15;
data.grabExcessVerticalSpace= false;
data.heightHint= SWTUtil.getTableHeightHint(table, Math.min(5, fCleanUpRefactoring.getProjects().length + 2));
data.grabExcessHorizontalSpace= true;
data.verticalAlignment= GridData.BEGINNING;
data= (GridData)settingsField.getButtonBox(null).getLayoutData();
data.grabExcessVerticalSpace= false;
data.verticalAlignment= GridData.BEGINNING;
data= (GridData)settingsField.getLabelControl(null).getLayoutData();
data.exclude= true;
settingsField.setElements(Arrays.asList(fCleanUpRefactoring.getProjects()));
settingsField.selectFirstElement();
fUseCustomField= new SelectionButtonDialogField(SWT.RADIO);
fUseCustomField.setLabelText(MultiFixMessages.CleanUpRefactoringWizard_use_custom_radio);
fUseCustomField.setSelection(isCustom);
fUseCustomField.doFillIntoGrid(composite, 2);
String settings= getDialogSettings().get(CUSTOM_PROFILE_KEY);
if (settings == null) {
fCustomSettings= JavaPlugin.getDefault().getCleanUpRegistry().getDefaultOptions(CleanUpConstants.DEFAULT_CLEAN_UP_OPTIONS).getMap();
} else {
try {
fCustomSettings= decodeSettings(settings);
} catch (CoreException e) {
JavaPlugin.log(e);
fCustomSettings= JavaPlugin.getDefault().getCleanUpRegistry().getDefaultOptions(CleanUpConstants.DEFAULT_CLEAN_UP_OPTIONS).getMap();
}
}
final BulletListBlock bulletListBlock= new BulletListBlock(composite, SWT.NONE);
GridData layoutData= new GridData(SWT.FILL, SWT.FILL, true, true);
layoutData.horizontalIndent= 15;
layoutData.grabExcessVerticalSpace= true;
bulletListBlock.setLayoutData(layoutData);
final Button configure= new Button(composite, SWT.NONE);
configure.setText(MultiFixMessages.CleanUpRefactoringWizard_ConfigureCustomProfile_button);
data= new GridData(SWT.TOP, SWT.LEAD, false, false);
data.widthHint= SWTUtil.getButtonWidthHint(configure);
configure.setLayoutData(data);
showCustomSettings(bulletListBlock);
configure.addSelectionListener(new SelectionAdapter() {
/**
* {@inheritDoc}
*/
@Override
public void widgetSelected(SelectionEvent e) {
Hashtable<String, String> workingValues= new Hashtable<String, String>(fCustomSettings);
CleanUpSelectionDialog dialog= new WizardCleanUpSelectionDialog(getShell(), workingValues);
if (dialog.open() == Window.OK) {
fCustomSettings= workingValues;
showCustomSettings(bulletListBlock);
}
}
});
updateEnableState(isCustom, settingsField, configure, bulletListBlock);
fUseCustomField.setDialogFieldListener(new IDialogFieldListener() {
public void dialogFieldChanged(DialogField field) {
updateEnableState(fUseCustomField.isSelected(), settingsField, configure, bulletListBlock);
}
});
Link preferencePageLink= new Link(composite, SWT.WRAP);
preferencePageLink.setText(MultiFixMessages.CleanUpRefactoringWizard_HideWizard_Link);
preferencePageLink.setFont(parent.getFont());
GridData gridData= new GridData(SWT.FILL, SWT.FILL, true, false);
gridData.widthHint= convertWidthInCharsToPixels(50);
gridData.horizontalSpan= 2;
preferencePageLink.setLayoutData(gridData);
preferencePageLink.addSelectionListener(new SelectionAdapter() {
/**
* {@inheritDoc}
*/
@Override
public void widgetSelected(SelectionEvent e) {
PreferencesUtil.createPreferenceDialogOn(composite.getShell(), CleanUpPreferencePage.PREF_ID, null, null).open();
}
});
setControl(composite);
Dialog.applyDialogFont(composite);
}
private void updateEnableState(boolean isCustom, final ListDialogField<IJavaProject> settingsField, Button configureCustom, BulletListBlock bulletListBlock) {
settingsField.getListControl(null).setEnabled(!isCustom);
if (isCustom) {
fEnableState= ControlEnableState.disable(settingsField.getButtonBox(null));
} else if (fEnableState != null) {
fEnableState.restore();
fEnableState= null;
}
bulletListBlock.setEnabled(isCustom);
configureCustom.setEnabled(isCustom);
}
private void showCustomSettings(BulletListBlock bulletListBlock) {
StringBuffer buf= new StringBuffer();
final ICleanUp[] cleanUps= JavaPlugin.getDefault().getCleanUpRegistry().createCleanUps();
CleanUpOptions options= new MapCleanUpOptions(fCustomSettings);
for (int i= 0; i < cleanUps.length; i++) {
cleanUps[i].setOptions(options);
String[] descriptions= cleanUps[i].getStepDescriptions();
if (descriptions != null) {
for (int j= 0; j < descriptions.length; j++) {
if (buf.length() > 0) {
buf.append('\n');
}
buf.append(descriptions[j]);
}
}
}
bulletListBlock.setText(buf.toString());
}
@Override
protected boolean performFinish() {
initializeRefactoring();
storeSettings();
return super.performFinish();
}
@Override
public IWizardPage getNextPage() {
initializeRefactoring();
storeSettings();
return super.getNextPage();
}
private void storeSettings() {
getDialogSettings().put(USE_CUSTOM_PROFILE_KEY, fUseCustomField.isSelected());
try {
getDialogSettings().put(CUSTOM_PROFILE_KEY, encodeSettings(fCustomSettings));
} catch (CoreException e) {
JavaPlugin.log(e);
}
}
private void initializeRefactoring() {
CleanUpRefactoring refactoring= (CleanUpRefactoring)getRefactoring();
CleanUpOptions options= null;
if (fUseCustomField.isSelected()) {
refactoring.setUseOptionsFromProfile(false);
options= new MapCleanUpOptions(fCustomSettings);
} else {
refactoring.setUseOptionsFromProfile(true);
}
refactoring.clearCleanUps();
ICleanUp[] cleanups= JavaPlugin.getDefault().getCleanUpRegistry().createCleanUps();
for (int i= 0; i < cleanups.length; i++) {
if (options != null)
cleanups[i].setOptions(options);
refactoring.addCleanUp(cleanups[i]);
}
}
public String encodeSettings(Map<String, String> settings) throws CoreException {
ByteArrayOutputStream stream= new ByteArrayOutputStream(2000);
try {
CleanUpProfileVersioner versioner= new CleanUpProfileVersioner();
CustomProfile profile= new ProfileManager.CustomProfile("custom", settings, versioner.getCurrentVersion(), versioner.getProfileKind()); //$NON-NLS-1$
ArrayList<Profile> profiles= new ArrayList<Profile>();
profiles.add(profile);
ProfileStore.writeProfilesToStream(profiles, stream, ENCODING, versioner);
try {
return stream.toString(ENCODING);
} catch (UnsupportedEncodingException e) {
return stream.toString();
}
} finally {
try { stream.close(); } catch (IOException e) { /* ignore */ }
}
}
public Map<String, String> decodeSettings(String settings) throws CoreException {
byte[] bytes;
try {
bytes= settings.getBytes(ENCODING);
} catch (UnsupportedEncodingException e) {
bytes= settings.getBytes();
}
InputStream is= new ByteArrayInputStream(bytes);
try {
List<Profile> res= ProfileStore.readProfilesFromStream(new InputSource(is));
if (res == null || res.size() == 0)
return JavaPlugin.getDefault().getCleanUpRegistry().getDefaultOptions(CleanUpConstants.DEFAULT_CLEAN_UP_OPTIONS).getMap();
CustomProfile profile= (CustomProfile)res.get(0);
new CleanUpProfileVersioner().update(profile);
return profile.getSettings();
} finally {
try { is.close(); } catch (IOException e) { /* ignore */ }
}
}
/**
* {@inheritDoc}
*/
public void updateStatus(IStatus status) {}
/**
* {@inheritDoc}
*/
public void valuesModified() {}
}
public CleanUpRefactoringWizard(CleanUpRefactoring refactoring, int flags) {
super(refactoring, flags);
setDefaultPageTitle(MultiFixMessages.CleanUpRefactoringWizard_PageTitle);
setWindowTitle(MultiFixMessages.CleanUpRefactoringWizard_WindowTitle);
setDefaultPageImageDescriptor(JavaPluginImages.DESC_WIZBAN_CLEAN_UP);
}
/* (non-Javadoc)
* @see org.eclipse.ltk.ui.refactoring.RefactoringWizard#addUserInputPages()
*/
@Override
protected void addUserInputPages() {
addPage(new CleanUpConfigurationPage((CleanUpRefactoring)getRefactoring()));
}
}